Почему в этот сценарий оболочки включены обратные слеши?

21

В моей копии conda.shсценария я вижу следующие строки:

if [ -n "${_CE_CONDA}" ] && [ -n "${WINDIR+x}" ]; then
    SYSP=$(\dirname "${CONDA_EXE}")
else
    SYSP=$(\dirname "${CONDA_EXE}")
    SYSP=$(\dirname "${SYSP}")
fi

Мне интересно, почему существует обратная косая черта в фронте dв dirname. Я не верю, что это необходимо. Такое использование обратной косой черты также появляется в других местах исходного файла. Есть ли причина для этого, что мне не хватает?

extremeaxe5
источник
2
Связанный: Выполните команду, которая
скрыта

Ответы:

30

Обратная косая черта будет подавлять расширение псевдонима, т.е. она выполняет исходную команду и следит за тем, чтобы версия псевдонима не запускалась. Скрипты могут неосознанно запускаться с расширением псевдонимов, когда система установила shopt -s expand_aliases(только BASH) или если она выполняется с использованием source.

./conda.sh          # usually no alias expansion (unless `shopt -s expand_aliases` in BASH)
source ./conda.sh   # alias expansion
. ./conda.sh        # alias expansion

Некоторым системным администраторам нравится ставить обратную косую черту во всем в качестве превентивной меры против побочных эффектов псевдонимов, просто на случай, если они были непреднамеренно псевдонимом где-то еще, и псевдоним расширяется, как объяснено ранее. Например, если система alias dirname='dirname -z'где-то установила это и условие позволяет раскрыть псевдоним, то, к сожалению, dirname -zвместо этого будет вызываться сценарий, который пытается вызвать dirname , что не было предназначено для сценария.

Если есть уверенность, что такого псевдонима не существует, мы можем удалить весь обратный слеш, и он должен работать нормально.

В качестве альтернативы можно использовать commandвместо версии с обратной косой чертой, чтобы подавить псевдоним. Таким образом, вместо \dirnameможно использовать command dirname, что может выглядеть более читабельным. (Для встроенных команд, таких как cd, следует использовать builtinвместо). Я предпочитаю это вместо этого, поскольку он также обходит функцию с тем же именем, что и любые псевдонимы.

otter.pro
источник
1
Также стоит отметить unalias -a, что удаляет все псевдонимы.
Сентиман
19
@Centimane Да, но обязательно сделайте, \unalias -aчтобы подавить расширение псевдонима
Бен C
Мог ли сисадмин тоже написать /usr/bin/dirname?
РонДжон
@RonJohn Да, он мог иметь в этом конкретном случае. Однако для некоторых программ разные дистрибутивы помещают их в разные каталоги. Один случай, который приходит на ум, - это /bin/edUbuntu против /usr/bin/edCentOS. Ввод полного пути делает скрипт менее переносимым.
doneal24
@ doneal24 как насчет чего-то вроде DIRNAME=$(which dirname), так whichкак не видит псевдонимов?
RonJohn
20

Если conda.shэто файл, предназначенный для поиска, то обратные косые черты предназначены для обхода псевдонимов. Bash обычно отключает расширение псевдонимов для выполнения скрипта, но для исходных файлов, которые могут работать в интерактивных оболочках, это не так. Так что просто dirnameможете запустить псевдоним с именем dirname, но \dirnameпропустите расширение псевдонима и запустите функцию или команду с именем dirname. (Однако, не просто обратная косая черта, подойдет любая цитата.)

Мур
источник
5
Или command dirname.
Кусалананда
7
( \command dirnameна тот случай, если кто-то также создал псевдоним command.): |
Муру
Почему он обходит псевдонимы? Является ли эта функциональность особым случаем чего-либо, или она должна быть жестко закодирована в bash (т.е. взломать)?
extremeaxe5
@ extremeaxe5 bash не выполняет расширение псевдонимов, если (любая часть) слово заключено в кавычки.
Муру
1
@ extremeaxe5, если вы спрашиваете, почему эта функция вообще существует, я не знаю. Именно в стандарте POSIX , однако: «имя команды слово [...] должно быть рассмотрено с целью определить , является ли он без кавычек , действительное имя псевдонима»
Мура