Почему бы не использовать «какие»? Что использовать тогда?

При поиске пути к исполняемому файлу или проверки того, что произойдет, если вы введете имя команды в оболочку Unix, существует множество различных утилит (, которые, type , команда, откуда, где, whereis, whatis, хэш и т. д.).

Мы часто слышим, что , который следует избегать. Зачем? Что мы должны использовать вместо этого?

263 голоса | спросил Stéphane Chazelas 2 AM00000020000001431 2013, 02:58:14

4 ответа


293

Вот и все, о чем вы никогда не думали, что никогда не захотите узнать об этом:

Резюме

Чтобы получить путь к исполняемому файлу в сценарии оболочки, подобном Bourne (есть несколько оговорок, см. ниже):

ls = $ (команда -v ls)

Чтобы узнать, существует ли какая-либо команда:

, если команда -v задана команда & gt; /DEV /нуль; тогда
  доступна команда эхо-команды
еще
  echo given-command недоступна
фи

В приглашении интерактивной оболочки, подобной Bourne:

тип ls

Команда , которая является сломанным наследием C-Shell и лучше оставлена ​​одна в оболочках Bourne.

Использовать случаи

Существует различие между поиском этой информации как частью скрипта или интерактивным в командной строке.

В приглашении оболочки типичный пример использования: эта команда ведет себя странно, я использую правильный? Что именно произошло, когда я набрал mycmd? Могу ли я посмотреть, что это такое?

В этом случае вы хотите знать, что делает ваша оболочка при вызове команды, не вызывая при этом команду.

В сценариях оболочки он имеет тенденцию отличаться. В сценарии оболочки нет причин, по которым вам нужно знать, где и что представляет собой команда, если все, что вы хотите сделать, это запустить ее. Как правило, то, что вы хотите знать, - это путь исполняемого файла, поэтому вы можете получить от него больше информации (например, путь к другому файлу относительно этого или прочитать информацию из содержимого исполняемого файла по этому пути).

Взаимодействующе, вы можете знать о all командах my-cmd, доступных в системе, в скриптах, редко так.

Большинство доступных инструментов (как это часто бывает) разработаны для интерактивного использования.

История

Сначала немного истории.

Ранние оболочки Unix до конца 70-х годов не имели никаких функций или псевдонимов. Только традиционный поиск исполняемых файлов в $ PATH. csh вводил псевдонимы около 1978 года (хотя csh был первым выпущен в 2BSD, в мае 1979 года), а также обработка .cshrc для пользователей для настройки оболочки (каждая оболочка, как csh, читает .cshrc, даже если она не является интерактивной, как в скриптах).

, в то время как оболочка Bourne была впервые выпущена в Unix V7 ранее в 1979 году, поддержка функций была добавлена ​​гораздо позже (1984 в SVR2), и в любом случае у нее никогда не было файла rc ( .profile предназначен для настройки вашей среды, а не оболочки per se ).

csh получил гораздо более популярную версию, чем оболочка Bourne (хотя он имел очень худший синтаксис, чем оболочка Bourne), он добавлял много более удобных и приятных функций для интерактивного использования.

В 3BSD (1980) для csh добавлен , который csh-скрипт для определения исполняемого файла. Вы можете найти немодифицированную копию этого скрипта из 3BSD там , и это едва ли другой скрипт, который вы можете найти как , который для многих коммерческих Unices в настоящее время (например, Solaris, HP /UX, AIX или Tru64).

Этот скрипт читает пользовательский ~ /.cshrc (как и все скрипты csh, если он не вызван с помощью csh -f)), и просматривает предоставленные имена команд в списке псевдонимов и в $ path (массив, который csh поддерживает на основе $ PATH).

Здесь вы идете, , который пришел первым для самой популярной оболочки в то время (и csh по-прежнему пользовался до середины 90-х годов), что является основной причиной почему он задокументирован в книгах и по-прежнему широко используется.

Обратите внимание, что даже для пользователя csh этот , который csh-скрипт не обязательно дает вам правильную информацию. Он получает псевдонимы, определенные в ~ /.cshrc, а не те, которые вы, возможно, определили позже в приглашении, или, например, через source ing другой csh и (хотя это не будет хорошей идеей), PATH может быть переопределен в ~ /.cshrc.

Запуск этой команды из оболочки Bourne будет по-прежнему искать алиасы, определенные в вашем ~ /.cshrc, но если у вас их нет, используйте csh, который, вероятно, вернет вам правильный ответ.

Аналогичная функциональность не была добавлена ​​в оболочку Bourne до 1984 года в SVR2 с помощью встроенной команды type. Тот факт, что он встроен (в отличие от внешнего скрипта), означает, что он может предоставить вам правильную информацию (в некоторой степени), поскольку он имеет доступ к внутренним компонентам оболочки.

Первоначальная команда type страдает от аналогичной проблемы, такой как , который, поскольку она не вернуластатус выхода из отказа, если команда не была найдена. Кроме того, для исполняемых файлов, в отличие от , который, он выводит что-то вроде ls is /bin /ls вместо простого /bin /ls, который сделал это менее проста в использовании в скриптах.

Unix Version 8 (не выпущен в дикой природе). В оболочке Bourne был встроен type, переименованный в whatis. И Plan9 (один из будущих преемников Unix) shell rc (и его производные, такие как akanga и es)) имеют whatis.

Оболочка Korn (подмножество которой основано на определении POSIX sh), разработанное в середине 80-х годов, но не широко доступное до 1988 года, добавило многие функции csh (линейный редактор, aliases ...) поверх оболочки Bourne. Он добавил свой собственный whence builtin (в дополнение к type), который принял несколько опций (-v, чтобы предоставить тип -образный подробный вывод и -p, чтобы смотреть только на исполняемые файлы (а не на псевдонимы /функции ...)).

В связи с проблемами, связанными с проблемами авторского права между AT & T и Berkeley, появилось несколько версий оболочки free software в конце 80-х начале 90-х годов. Вся оболочка Almquist (зола, которая должна быть заменена оболочкой Bourne в BSD), реализация общедоступного домена ksh (pdksh), bash (спонсируется FSF), zsh вышел между 1989 и 1991 годами.

Ash, хотя и означала замену для оболочки Bourne, не был встроен type до гораздо более позднего времени (в NetBSD 1.3 и FreeBSD 2.3), хотя он имел hash -v. OSF /1 /bin /sh имел встроенный тип, который всегда возвращал 0 до OSF /1 v3.x. bash не добавил откуда, но добавил -p для type для печати пути ( type -p будет выглядеть как from -p) и -a, чтобы сообщить all соответствующие команды. tcsh сделал , который добавил и добавил команду where, действующую как bash type -a код>. zsh имеет их все.

Оболочка fish (2005) имеет команду type, реализованную как функцию.

Скрипт , который csh был удален из NetBSD (поскольку он был встроен в tcsh и не очень использовался в других оболочках), а функциональность добавлена ​​в whereis ( при вызове , который, whereis ведет себя как , который, за исключением того, что он ищет только исполняемые файлы в $ PATH). В OpenBSD и FreeBSD , который также был изменен на один написанный на C, который ищет команды только в $ PATH.

Реализация

Существуют десятки реализаций команды , которая для разных Unices с различным синтаксисом и поведением.

В Linux (помимо встроенных в tcsh и zsh) мы находим несколько реализаций. Например, в недавних системах Debian это простой скрипт оболочки POSIX, который ищет команды в $ PATH.

busybox также имеет команду , которая.

Существует GNU , который, который, вероятно, является самым экстравагантным. Он пытается расширить то, что сделал сценарий , который csh сделал для других оболочек: вы можете сказать ему, что ваши псевдонимы и функции, чтобы он мог дать вам лучший ответ (и я считаю, что некоторые дистрибутивы Linux задают некоторые глобальные алиасы вокруг этого для bash).

zsh имеет пару операторов , чтобы развернуть путь к исполняемым файлам: оператор = имя_файла расширения и модификатор расширения : c (здесь применяется расширение ):

$ print -r - = ls
/бен /лс
$ cmd = ls; print -r - $ cmd: c
/бен /лс

zsh, в модуле zsh /parameters также делает хэш-таблицу команд как ассоциативный массив commands:

$ print -r - $ commands [ls]
/бен /лс

Утилита whatis (за исключением той, что находится в Unix V8 Bourne shell или Plan 9 rc /es)), действительно не связана с только для документации (greps the whatis database, то есть синопсис man-страницы).

whereis также был добавлен в 3BSD в то же время, что и , который, хотя он был написан в C, не csh и используется для одновременного поиска, исполняемого файла, справочной страницы и источника, но не на основе текущей среды. Опять же, это отвечает другой необходимости.

Теперь, на стандартном фронте, POSIX задает команды -v и -V (которые раньше были необязательными до POSIX.2008). UNIX задает команду type (нет опции). Вот и все (где, , который,откуда не указаны ни в одном стандарте)

До некоторой версии, type и команда -v были необязательными в спецификации Linux Standard Base, которая объясняет, почему, например, некоторые старые версии posh (хотя на основе pdksh, который был у обоих) тоже не было. Команда -v также была добавлена ​​в некоторые реализации оболочки Bourne (например, в Solaris).

Статус сегодня

В настоящее время статус состоит в том, что type и команда -v являются повсеместными во всех оболочках, подобных Bourne (хотя, как отмечено @jarno, обратите внимание на оговорку /ошибку в bash, если не в режиме POSIX или некоторых потомках оболочки Almquist ниже в комментариях). tcsh - единственная оболочка, в которой вы хотели бы использовать , который (поскольку там нет type и ), который ).

В оболочках, отличных от tcsh и zsh, , который может указать вам путь к данному исполняемому файлу, если нет псевдонима или функция с тем же именем в любом из наших ~ /.cshrc, ~ /.bashrc или любом файле запуска оболочки, и вы не определяете $ PATH в вашем ~ /.cshrc. Если у вас есть псевдоним или функция, определенные для него, он может или не может сказать вам об этом или сообщить вам неправильную вещь.

Если вы хотите узнать обо всех командах с заданным именем, нет ничего портативного. Вы должны использовать где в tcsh или zsh, type -a в bash или zsh, from -a в ksh93 и в других оболочках, вы можете использовать type в сочетании с , который -a который может работать.

Рекомендации

Получение имени пути к исполняемому файлу

Теперь, чтобы получить путь к исполняемому файлу в скрипте, есть несколько оговорок:

ls = $ (команда -v ls)

будет стандартным способом сделать это.

Есть несколько проблем:

  • Невозможно узнать путь исполняемого файла, не выполняя его. Все type, , которые, команда -v ... все используют эвристику, чтобы узнать путь. Они проходят через компоненты $ PATH и находят первый файл без каталога, для которого у вас есть разрешение на выполнение. Однако в зависимости от оболочки, когда дело доходит до выполнения команды, многие из них (Bourne, AT & T ksh, zsh, ash ...) будут просто выполнять их в порядке $ PATH пока системный вызов execve не будет возвращен с ошибкой. Например, если $ PATH содержит /foo: /bar и вы хотите выполнить ls, они сначала попытаются выполнить /foo /ls или если это не работает /bar /ls. Теперь выполнение /foo /ls может завершиться неудачно, потому что у вас нет разрешения на выполнение, но также по многим другим причинам, например, это недействительный исполняемый файл. Команда -v ls сообщит /foo /ls, если у вас есть разрешение на выполнение для /foo /ls, но выполняется ls code> может фактически запустить /bar /ls, если /foo /ls не является допустимым исполняемым файлом.
  • Если foo является встроенным или функцией или псевдонимом, команда -v foo возвращает foo. С некоторыми оболочками, такими как ash, pdksh или zsh, он также может возвращать foo, если $ PATH содержит пустую строку, и в текущем каталоге есть исполняемый файл foo. Есть некоторые обстоятельства, в которых вам может потребоваться это учитывать. Имейте в виду, например, что список встроенных компонентов зависит от реализации оболочки (например, mount иногда встроен для busybox sh) и, например, bash может получать функции из среды.
  • if $ PATH содержит относительные компоненты пути (обычно .) или пустую строку, которые относятся к текущему каталогу, но могут быть любыми), в зависимости от оболочки, < code> команда -v cmd может не выводить абсолютный путь. Таким образом, путь, который вы получаете в момент запуска команды -v, больше не будет действителен после того, как вы cd в другом месте.
  • Anecdotal: с оболочкой ksh93, если /opt /ast /bin (хотя этот точный путь может меняться в разных системах, я считаю) находится в вас $ PATH, ksh93 предоставит несколько дополнительных встроенных функций (chmod, cmp, cat ...), но команда -v chmod вернет /opt /ast /bin /chmod, даже если этот путь не существует.

Определение наличия команды

Чтобы узнать, существует ли стандартная команда, вы можете:

, если команда -v задана команда & gt; /DEV /нуль; тогда
  доступна команда эхо-команды
еще
  echo given-command недоступна
фи

Где можно было бы использовать, который

(т) CSH

В csh и tcsh у вас нет выбора. В tcsh это нормально, поскольку , который встроен. В csh это будет системная команда, которая может не делать то, что вы хотите в нескольких случаях.

найти команды только в некоторых оболочках

Случай, когда имеет смысл использовать , который, если вы хотите узнать путь к команде, игнорируя потенциальные встроенные оболочки или функции в bash, csh (не tcsh), dash или Bourne скрипты оболочки, то есть оболочки, у которых нет откуда -p (например, ksh или zsh)), command -ev (например, yash)) whatis -p (rc, akanga)) или встроенный который (например, tcsh или zsh) в системах, где , который доступен и не является сценарием csh.

Если эти условия выполнены, то:

echo = $ (который эхо)

предоставит вам путь к первому echo в $ PATH (за исключением случаев с углами), независимо от того, произойдет ли также echo быть оболочкой builtin /alias /function или нет.

В других оболочках вы предпочитаете:

  • zsh : echo == echo или echo = $ commands [echo] или echo = $ {$ {: - echo}: с}
  • ksh , zsh : echo = $ (откуда -p echo)
  • yash : echo = $ (команда -ev echo)
  • rc , akanga : echo = `whatis -p echo` (остерегайтесь путей с пробелами)
  • рыба : установить эхо (тип -fp echo)

Обратите внимание, что если все, что вы хотите сделать, это run , что команда echo, вам не нужно получать свой путь, вы можете просто сделать:

env echo, это не отражается встроенным эхом

Например, с tcsh, чтобы предотвратить использование встроенного , который:

set Echo = "` env which echo` "

, когда вам нужна внешняя команда

Другой случай, когда вы можете использовать , который, когда на самом деле нужна внешняя команда. POSIX требует, чтобы все встроенные оболочки (например, command) также были доступны в качестве внешних команд, но, к сожалению, это не относится к команде для многих систем. Например, редко можно найти команду command на операционных системах на базе Linux, в то время как в большинстве из них есть команда , которая (хотя разные с разными вариантами и поведением).

Случаи, в которых вы, возможно, захотите, чтобы внешняя команда была там, где вы могли бы выполнить команду без вызова оболочки POSIX.

Система («некоторая командная строка»), popen () ... функции C или разных языков вызывают оболочку для синтаксического анализа этой командной строки, поэтому Система («command -v my-cmd») работает в них. Исключением является perl, который оптимизирует оболочку, если не видит специального символа оболочки (кроме пробела). Это также относится к его оператору backtick:

$ perl -le 'print system "команда -v emacs"'
-1
$ perl -le 'print system ":; команда -v emacs"'
/USR /бен /Emacs
0

$ perl -e 'print `command -v emacs`'
$ perl -e 'print`:; команда -v emacs`'
/USR /бен /Emacs

Добавление этого :; выше заставляет perl вызывать там оболочку. Используя , который, вам не нужно будет использовать этот трюк.

ответил Brian Cotton 19 Jpm1000000pmFri, 19 Jan 2018 22:40:28 +030018 2018, 22:40:28
41

Причины, по которым не может быть использован , который уже был объяснен, но вот несколько примеров на нескольких системах, где , который действительно не работает.

В Bourne-подобных оболочках мы сравниваем вывод , который с выходом type (type), который является встроенной оболочкой, это значит, что это истинная истина, так как это оболочка говорит нам, как она будет вызывать команду).

Многие случаи - это corner , но имейте в виду, что , который /type часто используется в угловых случаях (чтобы найти ответ на неожиданное поведение вроде: почему эта команда ведет себя так, которую я вызываю? ).

Большинство систем, большинство Bourne-подобных оболочек: функции

Наиболее очевидный случай для функций:

$ type ls
ls - функция
ls ()
{
[-t 1] & & set - -F "$ @";
команда ls "$ @"
}
$, которое
/бен /лс

Причина, заключающаяся в том, что , который сообщает только о исполняемых файлах, а иногда и о псевдонимах (хотя и не всегда о вашей оболочке ), а не о функциях.

В GNU, у которой на странице man есть сломанные (поскольку они забыли процитировать $ @) пример о том, как использовать его для сообщения функций, а также, как и для псевдонимов, потому что он не реализовать синтаксический синтаксический анализатор оболочки, его легко обмануть:

$ which () {(alias; declare -f) | /usr /bin /which -tty-only --read-alias --read-functions -show-tilde --show-dot "$ @";}
$ f () {echo $ '\ n} \ ng () \ n {echo bar; \ n} \ n'>>> ~ /Foo; }
$ type f
f - функция
f ()
{
эхо "
}
г ()
{эхо-бар;
}
>>> ~ /Foo
}
$ type g
bash: type: g: not found
$, который f
f ()
{
эхо "
}
$, который g
г ()
{эхо-бар;
}

Большинство систем, большинство борнеподобных оболочек: встроенные

Еще один очевидный случай - встроенные или ключевые слова, поскольку , который является внешней командой, не имеет возможности узнать, какие встроенные оболочки вашей оболочки (и некоторые оболочки, такие как zsh, bash или ksh может динамически загружать встроенные функции):

$ type echo. время
эхо - встроенная оболочка
, это встроенная оболочка
время - это ключевое слово shell
$, который эхо. время
/Бен /эхо
который: нет. in (/bin: /usr /bin)
/USR /бен /время

(это не относится к zsh, где , который встроен)

Solaris 10, AIX 7.1, HP /UX 11i, Tru64 5.1 и многие другие:

$ csh
%, которое
ls: aliased to ls -F
% unalias ls
%, которое
ls: aliased to ls -F
% ksh
$, которое
ls: aliased to ls -F
$ type ls
ls - отслеживаемый псевдоним для /usr /bin /ls

Это потому, что в большинстве коммерческих Unices , который (например, в исходной реализации на 3BSD) является скриптом csh, который читает ~ /.cshrc. Алиасы, которые он будет сообщать, являются теми, которые определены там, независимо от псевдонимов, которые вы в настоящее время определили, и независимо от используемой вами оболочки.

В HP /UX или Tru64:

% echo 'setenv PATH /bin: /usr /bin'>>> ~ /.cshrc
% setenv PATH ~ /bin: /bin: /usr /bin
% ln -s /bin /ls ~ /bin /
%, которое
/бен /лс

(версии Solaris и AIX исправили эту проблему, сохранив $ path), прежде чем читать ~ /.cshrc и восстановить его перед поиском команд (ов)).

$ type 'a b'
a b есть /home /stephane /bin /a b
$, который 'a b'
нет a в /usr /sbin /usr /bin
нет b в /usr /sbin /usr /bin

Или:

$ d = "$ HOME /мой bin"
$ mkdir "$ d"; PATH = $ PATH: $ d
$ ln -s /bin /ls "$ d /myls"
$ type myls
myls is /home /stephane /my bin /myls
$, который myls
нет myls в /usr /sbin /usr /bin /home /stephane /мой bin

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

CentOS 6.4, bash

$ type, который
который имеет псевдоним для `alias | /usr /bin /который --tty-only --read-alias --show-dot --show-tilde '
$ alias foo = ': "| test |"'
$ foo
alias foo = ': "| test |"'
        /USR /бен /тест
$ alias $ 'foo = \ nalias bar ='
$ unalias bar
-bash: unalias: bar: не найден
$ который бар
alias bar = '

В этой системе существует псевдоним, определенный в системе, который обертывает команду GNU .

Поддельный вывод - это потому, что , который считывает вывод bash alias, но не знает, как правильно его разобрать и использует эвристика (один псевдоним в строке, ищет первую найденную команду после |, ;, & ...)

Самая худшая вещь в CentOS заключается в том, что zsh имеет отличную команду , которая встроена, но CentOS удалось ее разбить, заменив ее нерабочим псевдонимом на GNU < код>, который.

Debian 7.0, ksh93:

(хотя применяется к большинству систем со многими оболочками)

$ unset PATH
$, который
/USR /местные /бен /который
$ type, который
который является отслеживаемым псевдонимом для /bin /, который

В Debian, /bin /который является/bin /sh. В моем случае sh является dash, но это то же самое, когда это bash.

Unset PATH не отключает поиск PATH, а означает использование default PATH системы, который, к сожалению, на Debian, никто не соглашается ( dash и bash имеют /usr /local /sbin: /usr /local /bin: /usr /sbin: /usr /bin: /sbin: /bin, zsh имеет /bin: /usr /bin: /usr /ucb: /usr /local /bin, ksh93 имеет /bin: /usr /bin, mksh имеет /usr /bin: /bin ($ (getconf PATH) ), execvp () (например, в env) имеет : /bin: /usr /bin (да, сначала выглядит в текущем каталоге !)).

Вот почему , который получает неверное значение выше, поскольку использует dash по умолчанию PATH, который отличается от ksh93 код> 's

Не лучше с GNU , который сообщает:

, который: no, который в ((null))

(Интересно, что в моей системе действительно есть /usr /local /bin /which, который на самом деле является скриптом akanga, который поставляется с akanga (производная оболочки rc, где по умолчанию PATH) есть /usr /ucb: /usr /bin: /bin:.))

bash, любая система:

Один Крис ссылается на свой ответ :

$ PATH = $ HOME /bin: /bin
$ ls /dev /null
/DEV /нуль
$ cp /bin /ls bin
$ type ls
ls hashed (/bin /ls)
$ command -v ls
/бен /лс
$, которое
/главная /Chazelas /бен /лс

Также после вызова hash вручную:

$ type -a, который
который является /usr /local /bin /который
который /usr /bin /, который
который является /bin /который
$ hash -p /bin /, который
$, который
/USR /местные /бен /который
$ type, который
который хэшируется (/bin /which)

Теперь случай, когда , который, а иногда type не работает:

$ mkdir a b
$ echo '#! /bin /echo'> а /Foo
$ echo '#! /'> б /Foo
$ chmod + x a /foo b /foo
$ PATH = b: a: $ PATH
$ foo
б /Foo
$ type foo
foo - b /foo

Теперь, с некоторыми оболочками:

$ foo
bash: ./b/foo: /: плохой интерпретатор: разрешение отклонено

С другими:

$ foo
а /Foo

Ни , который, ни type не может заранее знать, что b /foo не может быть выполнен. Некоторые оболочки, такие как bash, ksh или yash, при вызове foo, действительно попытаются запустить b /foo и сообщить об ошибке, в то время как другие (например, zsh, ash, csh, Bourne), tcsh) будет запускать a /foo после отказа системного вызова execve () на b /foo.

ответил Stéphane Chazelas 9 AM000000120000001731 2013, 00:58:17
21

Одна вещь, которая (из моего быстрого обезжиривания) кажется, что Стефан не упомянул, что , который не знает о хэш-таблице пути вашей оболочки. Это приводит к тому, что он может вернуть результат, который не отражает того, что фактически выполняется, что делает его неэффективным при отладке.

ответил Chris Down 2 AM000000110000003031 2013, 11:53:30
4

что такое

  

Мы часто слышим то, чего следует избегать. Почему?

Я не понимаю, почему это должно быть «часто сказано».

Какой инструмент, как и любой другой. Полезно при некоторых условиях и для некоторых целей. Короче говоря:

  • Каков инструмент поиска внешних исполняемых файлов в некоторых оболочках.

  • Как правило (в системах, которые он установил) также внешний исполняемый файл.

Простая команда , которая показывает:

ash: /usr /bin /, который
рыба: /usr /bin /которая
rc: /usr /bin /который
yash: /usr /bin /, который
tcsh: which: shell встроенная команда.
csh: which: shell встроенная команда.
тире: /usr /bin /, который
zsh /sh: which: shell встроенная команда
bash: /usr /bin /который
lksh: /usr /bin /который
mksh: /usr /bin /который
ksh93: /usr /bin /который
attsh: /usr /bin /который
zsh /ksh: который: встроенная команда
zsh: который: встроенная команда

Как обычно, csh /tcsh /zsh работают «особым образом». Обычный трюк вызова команды с backspace \ который работает в csh /tcsh, но сбой в rc. Единственным оставшимся «специальным» является zsh:

$ zsh -c '\ который, который'
который: встроенная командная оболочка

Единственный верный путь - использовать полный путь, который работает во всех оболочках:

/usr /bin /, который

зола: /usr /bin /
рыба: /usr /bin /которая
rc: /usr /bin /который
yash: /usr /bin /, который
tcsh: /usr /bin /, который
csh: /usr /bin /который
тире: /usr /bin /, который
zsh /sh: /usr /bin /который
bash: /usr /bin /который
lksh: /usr /bin /который
mksh: /usr /bin /который
ksh93: /usr /bin /который
attsh: /usr /bin /который
zsh /ksh: /usr /bin /, который
zsh: /usr /bin /, который

Это прекрасно объясняет, почему он не будет сообщать строгие внутренние команды оболочки:

/usr /bin /, которые продолжаются

зола:
рыба            :
rc:
yash:
tcsh:
csh:
тире:
zsh /sh:
bash:
lksh:
mksh:
ksh93:
attsh:
zsh /ksh:
zsh:

И, конечно, внешний инструмент не может знать о внутренних псевдонимах, функциях, встроенных таблицах, хэш-таблицах или о том, что оболочка может использовать.

Какой не правильный инструмент для запроса оболочки.

И вот здесь начинается вся история и сложности.

Основной вопрос, который не может ответить (внешний):

  • Какая команда будет выполняться, когда командной строке присваивается оболочке?

Единственный, кто действительно может ответить, это сама оболочка. Некоторые общие моменты (оставляя некоторые детали):

  • Команда для выполнения - это первое слово командной строки (кроме if, for и нескольких других составных команд), которое не является перенаправлением или присваиванием переменной.
  • Это первое исполняемое слово расширяется с помощью любого соответствующего псевдонима. Первое слово снова выбрано.
  • Последнее слово выполняется в списке определенных функций.
  • Если функция не найдена, слово заносится в список хешированных команд (ранее выполнявшихся команд).
  • Если слово не найдено в хеш-таблице, поиск пути выполняется.

Все вышесказанное выполняется оболочкой, поэтому единственный способ узнать, что будет выполняться, - это запросить оболочку.

type и команда

Команды type и -v запрашиваются POSIX. Их следует ожидать, чтобы они работали в большинстве оболочек, и они делают, за исключением csh и tcsh. Следующий список о type (команда похожа) не включает в себя рыбу или rc. На рыбе type работает, когда рыба интерактивна. Но не работает скрипт. Я также оставляю в стороне rc, где тип также терпит неудачу.:

тип ls

зола: ls is /bin /ls
yash: ls: внешняя команда в /bin /ls
tcsh: type: Команда не найдена.
csh: type: Команда не найдена.
тире: ls is /bin /ls
zsh /sh: ls is /bin /ls
bash: ls is /bin /ls
lksh: ls - отслеживаемый псевдоним для /bin /ls
mksh: ls - отслеживаемый псевдоним для /bin /ls
ksh93: ls - отслеживаемый псевдоним для /bin /ls
attsh: ls - отслеживаемый псевдоним для /bin /ls
zsh /ksh: ls is /bin /ls
zsh: ls is /bin /ls

В csh /tcsh для запроса оболочки следует использовать внутренний (встроенный) , который (а не внешний /bin /which).

Затем есть откуда, где, whereis, whatis),hash и некоторые другие. Все разные ответы на один и тот же вопрос. Все работают по-разному в разных оболочках. Вероятно, откуда является наиболее распространенным после type. Другие - специальные решения, которые не отвечают на точно тот же вопрос. Вот где начинается вся сложность.

  

Что мы должны использовать вместо этого?

Это зависит от вопроса.

  • Для чего будет выполняться оболочка, используйте тип, откуда или команду (возможно).

  • Для чего внешний исполняемый файл данного имени существует, используйте внешний который (некоторые встроенные функции делают другое).

ответил Isaac 15 Mayam18 2018, 00:53:21

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132