Заказ исполняемых файлов начался в Bash

14

Если я выполняю testкоманду в bash, testзапускается встроенная утилита (оценивает условное выражение):

$ type test
test is a shell builtin
$ type -a test
test is a shell builtin
test is /usr/local/bin/test
test is /usr/bin/test
$ 

Однако, как видно из выходных данных type -a testвыше, testв каталоге / usr / local / bin есть еще один, а в каталоге / usr / bin - еще один. Как упорядочены исполняемые файлы, т. Е. Всегда ли предпочтительнее встроенные команды, а затем остальные команды зависят от порядка каталогов в переменной $ PATH? Кроме того, возможно ли изменить порядок запуска исполняемых файлов, например, если я наберу test, тогда запускается / usr / bin / test вместо bash-builtin test?

Мартин
источник
Вы можете указать полный путь при вызове команды, например, /usr/bin/test -f "$file"...
jasonwryan
@jasonwryan Я знаю об этом, но мне просто интересно, есть ли способ изменить порядок запуска исполняемых файлов.
Мартин

Ответы:

25

Наивысшим приоритетом является псевдоним bash, затем специальные встроенные функции (только в режиме POSIX), затем функции, затем встроенные функции, а затем поиск в $PATH.

Чтобы выполнить встроенную функцию, используйте builtin test.
Чтобы выполнить внешнюю программу, использовать явный путь: /bin/test.
Чтобы игнорировать функции и псевдонимы, используйте command test.
Чтобы обойти только псевдоним, используйте \testили любой другой вид расширения.

Можно отключить / включить встроенную функцию enable test.

(Обновлено в соответствии с комментариями ниже)
(Исправлено некорректное редактирование админкой, которое disableвстроено в bash - фактически, есть только enable)

gena2x
источник
1
@ 1_CR gena2x прав. В моем ответе пропущены специальные встроенные функции, которые имеют приоритет над функциями согласно POSIX (хотя некоторые оболочки не совместимы; bash соответствует только в режиме POSIX).
Жиль "ТАК - перестань быть злым"
1
Рекомендуемое редактирование: псевдонимы отключаются, когда вы цитируете команду (или любую ее часть), как в \testили 'test'или tes't'.
Джон Кугельман
2
Это не полная картина. Кажется, что любое расширение (в руководстве по bash, все подстановки, расширение тильды и т. Д. Называется расширением ) отключает псевдонимы. Я старался.
gena2x
1
Цитата со страницы Баш человека:.. «Первое слово каждой простой команды, если без кавычек, проверяется , чтобы увидеть , если он имеет псевдоним Если это так, то слово заменяется текстом псевдонима Символы /, $, кавычка, и =и любые метасимволы оболочки или символы цитирования, перечисленные выше, могут не отображаться в псевдониме ".
Джон Кугельман
2
+1 за подсказки, помогающие мне найти источник этой информации: она находится на странице руководства bash, в разделе COMMAND EXECUTION, второй и третий абзацы.
twan163
6

Встроенные команды всегда предпочтительнее внешних команд. Смысл в том, что встроенная команда работает быстрее (и в некоторых случаях, например, cdили , только встроенная команда может дать желаемый эффект).test -o BASH_OPTION

Иногда внешняя команда может иметь возможности, которых нет у встроенной оболочки. В этом случае вы можете вызвать внешнюю команду, указав явный путь (то есть, содержащий косую черту) (это обходит любые опасения по поводу порядка в $PATH). Если вы не хотите жестко кодировать внешний путь, но хотите запретить использование встроенной функции, вы можете использовать "$(type -P test)"(примечание заглавную P) в bash, "$(whence -p test)"в ksh и =testв zsh. Другой способ принудительного использования внешней команды - использовать commandвстроенный ( command -p test …) или пройти через envутилиту ( env test …).

В zsh вы можете отключить встроенную функцию с помощью disable test. Это постоянно (для текущей оболочки или подоболочки), пока встроенная функция не будет включена enable test. В bash вы можете сделать то же самое с enable -n testотключением и enable testвключением.

Вы можете использовать псевдоним или функцию для принудительного выполнения другой команды, например alias test=/usr/bin/testили test () { /usr/bin/test "$@"; }. Если у вас есть такой псевдоним, вы можете запретить его использование, заключив в кавычки любую его часть, например, \testбудет выполнять обычную функцию / встроенный / внешний поиск. Обратите внимание, что в зависимости от оболочки и ее настроек определения псевдонимов в функции могут быть расширены при чтении функции или при ее выполнении. Если вы определили функцию, вы можете использовать ее command testдля предотвращения поиска функций, а также поиска псевдонимов (поэтому здесь testвстроенная функция будет вызываться, если она не отключена).

Жиль "ТАК - перестань быть злым"
источник
envздесь тоже не подойдет?
Стивен Пенни
Итак, если оболочка запускается из BusyBox, другие, обычно внешние команды из того же BusyBox считаются внутренними? Например, я добавил полный dfк PATH на первой позиции, удалил псевдоним 'df', which dfпоказывает / opt / bin / df, но df запускает / bin / df -> busybox
papo
@papo which dfне обязательно показывает вам, что dfработает. unix.stackexchange.com/questions/85249/…
Жиль "ТАК, перестань быть злым"