В сценарии 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
Почему это было бы? Как я могу заставить это обнаруживать файл, когда имя файла находится в переменной?
Интересный вопрос. Замена $ 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
, и, похоже, он работает, предлагаю вам подтвердить в вашем конкретном случае.