Сценарий Bash -e не определяет имя файла в переменной - PullRequest
5 голосов
/ 28 июня 2010

В скрипте 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

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

1 Ответ

7 голосов
/ 28 июня 2010

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

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

+ [ -e ~/... ]

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

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

и работает .

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

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

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


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

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

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

Одна вещь, которую вы могли бы сделать, - это изменить ваше if утверждение на:

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...