Сценарий Bash-e не обнаруживающий имя файла в переменной

В сценарии Bash я пытаюсь обнаружить, существует ли файл. Имя файла находится в переменной, но команда-e, кажется, не может обнаружить файл. Следующий код всегда выводы "~/misc/tasks/drupal_backup.sh не существует"

filename="~/misc/tasks/drupal_backup.sh"

if [ -e "$filename" ]; then
  echo "$filename exists"
else 
  echo "$filename does not exist"
fi

С другой стороны, следующий код обнаруживает файл правильно:

if [ -e ~/misc/tasks/drupal_backup.sh ]; then
  echo "$filename exists"
else 
  echo "$filename does not exist"
fi

Почему это было бы? Как я могу заставить это обнаруживать файл, когда имя файла находится в переменной?

5
задан thornate 28 June 2010 в 02:41
поделиться

1 ответ

Интересный вопрос. Замена $ HOME на ~ работает так же, как удаление кавычек из присваивания.

Если вы поместите set -x вверху этого скрипта, вы увидите, что версия с кавычками устанавливает для имени файла значение ~ / ... , что и указано к -e . Если вы удалите кавычки, для имени файла будет установлено расширенное значение / home / something / ... . Итак, в первом случае вы видите:

+ [ -e ~/... ]

, и ему это не нравится. Во втором случае вы видите:

+ [ -e /home/somebody/... ]

и это действительно работает.

Если вы сделаете это без переменной, вы увидите:

+ [ -e /home/somebody/... ]

и да, это работает.


После небольшого исследования я обнаружил, что на самом деле это порядок, в котором bash выполняет свои расширения. На странице руководства bash:

Порядок раскрытия следующий: раскрытие фигурных скобок, раскрытие тильды, раскрытие параметров, переменных и арифметических операций и подстановка команд (выполняется слева направо), разделение слов и раскрытие имени пути.

Поэтому не работает, переменная подставляется после тильды. Другими словами, в точке, где bash хочет развернуть ~ , его нет. Только после раскрытия переменной слово меняется на ~ / ... , и после этого тильды не раскрываются.

Единственное, что вы могли бы сделать, - это изменить свой оператор if на:

if [[ -e $(eval echo $filename) ]]; then

Это позволит вычислить аргумент $ filename дважды.В первый раз (с eval ) на этапе раскрытия тильды не будет ~ , но $ filename будет изменено на ~ / .. . во время фазы переменного расширения.

Затем при второй оценке (выполняемой как часть самого if ) ~ будет там во время фазы раскрытия тильды.

Я проверил это в моем файле .profile , и, похоже, он работает, предлагаю вам подтвердить в вашем конкретном случае.

7
ответ дан 14 December 2019 в 08:40
поделиться