Когда вы пытаетесь найти файл, не хотите ли вы сказать, что файл не существует, и вы знаете, что исправить?
Например, nvm рекомендует добавить это в свой профиль / rc:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
С вышеупомянутым, если nvm.sh
не существует, вы получите «тихую ошибку». Но если вы попробуете . "$NVM_DIR/nvm.sh"
, выход будет FILE_PATH: No such file or directory
.
shell-script
JBallin
источник
источник
HOME
.Ответы:
В оболочках POSIX
.
это специальная встроенная функция, поэтому ее сбой приводит к выходу оболочки (в некоторых оболочках, напримерbash
, это происходит только в режиме POSIX).То, что считается ошибкой, зависит от оболочки. Не все из них выходят из-за синтаксической ошибки при разборе файла, но большинство из них завершается, когда исходный файл не может быть найден или открыт. Я не знаю ничего, что могло бы завершиться, если последняя команда в исходном файле вернулась с ненулевым статусом выхода (если,
errexit
конечно, опция не включена).Здесь делают:
Это тот случай, когда вы хотите получить исходный файл, если он там, и нет, если его нет (или здесь пусто
-s
).То есть, это не должно считаться ошибкой (фатальная ошибка в оболочках POSIX), если файла нет, этот файл считается необязательным файлом.
Это все равно будет (фатальной) ошибкой, если файл не будет читаемым, или каталогом, или (в некоторых оболочках) при синтаксической ошибке при синтаксическом анализе, которая будет представлять собой реальные ошибки, о которых следует сообщать.
Некоторые утверждают, что есть состояние гонки. Но единственное, что это означает, это то, что оболочка завершит работу с ошибкой, если файл будет удален между
[
и.
, но я бы сказал, что допустимо считать ошибкой, что этот файл с фиксированным путем внезапно исчезнет, пока скрипт Бег.С другой стороны,
где
command
¹ удаляет специальный атрибут.
команды (поэтому он не выходит из оболочки при ошибке) не будет работать так:.
ошибки, но также и ошибки команд, выполняемых в исходном файлеДругие распространенные синтаксисы (см., Например,
grep -r /etc/default /etc/init*
в системах Debian сценарии инициализации, в которые еще не были преобразованыsystemd
(гдеEnvironmentFile=-/etc/default/service
вместо этого используется дополнительный файл среды)):[ -e "$file" ] && . "$file"
Проверьте файл, который там есть, все равно отправьте его, если он пуст. Все еще фатальная ошибка, если она не может быть открыта (даже если она там или была там). Вы можете увидеть больше вариантов, таких как
[ -f "$file" ]
(существует и является обычным файлом),[ -r "$file" ]
(доступно для чтения) или их комбинаций.[ ! -e "$file" ] || . "$file"
Немного лучшая версия. Проясняет, что несуществующий файл является нормальным случаем. Это также означает, что
$?
будет отображать состояние выхода последней команды, запущенной в$file
(в предыдущем случае, если вы получаете1
, вы не знаете, потому что$file
это не было или эта команда не выполнена).command . "$file"
Ожидайте, что файл будет там, но не выходите, если он не может быть интерпретирован.
[ ! -e "$file" ] || command . "$file"
Комбинация вышесказанного: все нормально, если файла нет, а для оболочек POSIX сообщается об ошибках открытия (или разбора) файла, но они не являются фатальными (что может быть более желательным для
~/.profile
).¹ Примечание:
zsh
однако, вы не можете использоватьcommand
это, если не вsh
эмуляции; обратите внимание, что в оболочке Korn,source
на самом деле псевдоним дляcommand .
, не особый вариант.
источник
.bash_profile
. Я думаю, что лучше, чем потом сожалеть, но есть ли когда-нибудь bash в режиме POSIX, когда.bash_profile
он получен?bash
когда не в режиме POSIX. Вы захотите,[ -e /file ] && . /file
если не считаете это ошибкой, когда файл не существует. Источник try затем обрабатывает ошибку, если она не может быть выполнена здесь..
уже сообщит об ошибке (на stderr). И если намерение состоит в том, чтобы не считать это ошибкой, когда файл не существует, это неверно (и это невозможно, из состояния выхода сказать,.
что произошел сбой, потому что файл не существует или не был читаемым, или был не анализируется, или последняя команда не выполнена), что я и подчеркиваю в этом ответе.Ответственный за
nvm
ответ:Моя интерпретация (в сочетании с превосходным объяснением Стефана и комментарием Кусалананды):
Это проще и безопаснее.
Он защищает от оболочек POSIX, выходящих при запуске из-за отсутствия файла (по разным причинам). Те, кто использует не POSIX (например, bash) оболочки, могут удалить условные, если они того пожелают.
источник
/etc
, то это позволяет некоторым пользователям иметь файл, а другим - нет. ИМХО,nvm
ответ сопровождающего касается только одного аспекта.Как указали JBallin и Stéphane Chazelas , в оболочках POSIX поиск несуществующего файла может привести к сбою входа.
Но добавление теста, чтобы увидеть, существует ли файл, а затем попытка получить его, может вызвать состояние гонки. Если что-то изменится
nvm.sh
между[ -s nvm.sh ]
и. nvm.sh
, это вызовет именно ту ошибку, которую они пытаются предотвратить, хотя и гораздо реже.В общем, способ предотвратить состояние гонки - просто попробовать то, что вы хотите сделать, а затем обработать ошибку в случае сбоя, например
Оказывается, это не работает в оболочках POSIX, потому что, как и выше,
.
сбой приведет к немедленному завершению работы оболочки до того, как может быть запущена любая обработка ошибок.Мой ответ утверждает, что оболочки POSIX не имеют отношения к этому вопросу, потому что
.bash_profile
никогда не должны работать в режиме POSIX. Так что в любом случае мы можем просто выполнить приведенный выше код.Чтобы быть максимально безопасным, мы могли бы убедиться, что режим POSIX не действует, или убедиться, что режим POSIX отключен, используя методику, описанную в /unix//a/383581/3169 .
Ответ Стефана содержит несколько полезных советов о том, как обращаться со всеми оболочками POSIX, что, как мне кажется, было намерением автора nvm, но несколько отличалось от того, о чем здесь задавался вопрос, поэтому у нас есть несколько возможных подходов, в зависимости от вашей цели. ,
источник