Заказ исполняемых файлов начался в 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)


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/…
Жиль "ТАК, перестань быть злым"
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.