Ища путь к исполняемому или проверить , что произойдет , если ввести имя команды в оболочке Unix, существует множество различных утилит ( which
, type
, command
, whence
, where
, whereis
, whatis
, hash
и т.д.).
Мы часто слышим, что этого which
следует избегать. Почему? Что мы должны использовать вместо этого?
shell
history
which
portability
Стефан Шазелас
источник
источник
which
предполагают наличие интерактивного контекста оболочки. Этот вопрос помечен / переносимость. Поэтому я интерпретирую вопрос в этом контексте как «что использовать вместо того,which
чтобы найти первый исполняемый файл с заданным именем в$PATH
». Большинство ответов и аргументов противwhich
псевдонимов, встроенных функций и функций, которые в большинстве реальных переносимых сценариев оболочки представляют только академический интерес. Локально определенные псевдонимы не наследуются при запуске сценария оболочки (если вы его не используете.
).csh
(иwhich
все еще являетсяcsh
сценарием для большинства коммерческих Unices) действительно читает,~/.cshrc
когда не интерактивен. Вот почему вы заметите, что csh-скрипты обычно начинаются с#! /bin/csh -f
.which
не потому, что он стремится дать вам псевдонимы, потому что он предназначен как инструмент для (интерактивных) пользователейcsh
. POSIX оболочки пользователи имеютcommand -v
.(t)csh
(или вы не возражаете, если она не даст вам правильный результат), используйтеtype
илиcommand -v
вместо . Смотрите ответы почему .stat $(which ls)
неправильно по нескольким причинам (пропущено--
, пропущены кавычки), не только использованиеwhich
). Вы бы использовалиstat -- "$(command -v ls)"
. Предполагается, чтоls
это действительно команда, найденная в файловой системе (не встроенная оболочка или функция псевдонима).which
может дать вам неправильный путь (а не путь, который будет выполнять ваша оболочка, если вы введетеls
) или псевдоним, определенный в конфигурации некоторых других оболочек ...which
реализации не дают вам даже того,ls
что будет найдено при поиске$PATH
(независимо от того, чтоls
может вызываться в вашей оболочке).sh -c 'command -v ls'
илиzsh -c 'rpm -q --whatprovides =ls'
, скорее всего, даст вам правильный ответ. Дело в том, чтоwhich
это разрушенное наследиеcsh
.Ответы:
Вот все, о чем вы никогда не думали, что никогда не захотите узнать об этом:
Резюме
Чтобы получить путь к исполняемому файлу в Bourne-подобном сценарии оболочки (есть несколько предостережений; см. Ниже):
Чтобы узнать, существует ли данная команда:
По приглашению интерактивной оболочки типа Борна:
which
Команда сломанное наследие от C-Shell и лучше оставить в покое в Bourne-подобных оболочках.Сценарии использования
Существует различие между поиском этой информации как части скрипта или в интерактивном режиме в приглашении оболочки.
В командной строке типичный вариант использования: эта команда ведет себя странно, я использую правильный? Что именно произошло, когда я напечатал
mycmd
? Могу ли я посмотреть дальше, что это такое?В этом случае вы хотите знать, что делает ваша оболочка, когда вы вызываете команду, фактически не вызывая команду.
В сценариях оболочки это обычно бывает по-другому. В сценарии оболочки нет причины, по которой вы хотели бы знать, где или что представляет команда, если все, что вы хотите сделать, это запустить ее. Как правило, вам нужно знать путь к исполняемому файлу, чтобы вы могли получить из него больше информации (например, путь к другому файлу относительно этого или прочитать информацию из содержимого исполняемого файла по этому пути).
Интерактивный, вы можете захотеть узнать о всех тех
my-cmd
командах , доступных в системе, в сценариях, редко так.Большинство доступных инструментов (как это часто бывает) были разработаны для интерактивного использования.
история
Сначала немного истории.
Ранние оболочки Unix до конца 70-х не имели никаких функций или псевдонимов. Только традиционный поиск исполняемых файлов в
$PATH
.csh
в 1978 году были введены псевдонимы (хотяcsh
впервые был выпущен в2BSD
мае 1979 года), а также обработка.cshrc
для пользователей настройки оболочки (каждая оболочка, какcsh
считывается,.cshrc
даже когда она не интерактивна, как в сценариях).Хотя оболочка Bourne была впервые выпущена в Unix V7 в начале 1979 года, поддержка функций была добавлена гораздо позже (1984 в SVR2), и в любом случае у нее никогда не было
rc
файла (.profile
предназначенного для настройки среды, а не оболочки как таковой ).csh
стала намного более популярной, чем оболочка Bourne, поскольку (хотя она имела ужасно худший синтаксис, чем оболочка Bourne), она добавила множество более удобных и приятных функций для интерактивного использования.В
3BSD
1980 году для пользователей был добавленwhich
сценарий csh,csh
помогающий идентифицировать исполняемый файл, и это едва ли другой сценарий, который вы можете найти, как иwhich
во многих коммерческих Unices в настоящее время (например, Solaris, HP / UX, AIX или Tru64).Этот сценарий читает пользователя
~/.cshrc
(как и всеcsh
сценарии, если только он не вызываетсяcsh -f
) и ищет предоставленные имена команд в списке псевдонимов и в$path
(массив, которыйcsh
поддерживается на основе$PATH
).Итак, вы
which
пришли первым для самой популярной оболочки в то время (иcsh
все еще были популярны до середины 90-х), что является основной причиной, почему она была задокументирована в книгах и до сих пор широко используется.Обратите внимание, что даже для
csh
пользователя этотwhich
сценарий csh не обязательно дает вам правильную информацию. Он получает псевдонимы, определенные в~/.cshrc
, а не те, которые вы, возможно, определили позже в приглашении или, например, с помощьюsource
другогоcsh
файла, и (хотя это не будет хорошей идеей)PATH
могут быть переопределены в~/.cshrc
.Выполнение этой
which
команды из оболочки Bourne будет по-прежнему искать псевдонимы, определенные в вашем~/.cshrc
, но если их нет, потому что вы их не используетеcsh
, это все равно, вероятно, даст вам правильный ответ.Подобная функциональность не была добавлена в оболочку Bourne до 1984 года в SVR2 с помощью
type
встроенной команды. Тот факт, что он встроен (в отличие от внешнего скрипта), означает, что он может дать вам правильную информацию (в некоторой степени), поскольку он имеет доступ к внутренним компонентам оболочки.Первоначальная
type
команда страдала от проблемы, аналогичнойwhich
скрипту, в том, что она не возвращала состояние завершения сбоя, если команда не была найдена. Кроме того, для исполняемых файлов, напротивwhich
, он выводит что-то вроде,ls is /bin/ls
а не просто,/bin/ls
что делает его менее простым в использовании в скриптах.В оболочке Bourne версии 8 Unix (не выпущенной в дикой природе) ее
type
встроенное имя было переименованоwhatis
. И оболочка Plan9 (некогда преемник Unix)rc
(и ее производные, такие какakanga
иes
) также имеютwhatis
.Оболочка Korn (подмножество, на котором основано определение POSIX sh), разработанная в середине 80-х годов, но не получившая широкого распространения до 1988 года, добавила многие
csh
функции (редактор строк, псевдонимы ...) поверх оболочки Bourne. , Он добавил свою собственнуюwhence
встроенную функцию (в дополнение кtype
), которая приняла несколько опций (-v
для обеспеченияtype
подробного вывода -подобного вывода и-p
поиска только исполняемых файлов (не псевдонимов / функций ...)).Совсем случайно, в связи с проблемами авторского права между AT & T и Беркли, в конце 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
имеетtype
встроенную функцию, которая всегда возвращает 0 до OSF / 1 v3.x.bash
не добавил,whence
но добавил-p
опцию, чтобыtype
напечатать путь (type -p
будет похожеwhence -p
) и-a
сообщить обо всех соответствующих командах.tcsh
сделалwhich
встроенный и добавилwhere
команду, действующую какbash
'stype -a
.zsh
есть их все.fish
Оболочка (2005) имеетtype
команду реализована в виде функции.Тем
which
временем сценарий csh был удален из NetBSD (поскольку он был встроен в tcsh и не очень используется в других оболочках), а функциональность была добавлена к немуwhereis
(когда вызывается какwhich
,whereis
ведет себя как,which
за исключением того, что он просматривает только исполняемые файлы$PATH
). В OpenBSD и FreeBSDwhich
также был изменен на тот, что написан на C, который ищет только команды$PATH
.Реализации
Существуют десятки реализаций
which
команды в различных Unices с разным синтаксисом и поведением.В Linux (кроме встроенных в
tcsh
andzsh
) мы находим несколько реализаций. Например, в последних системах Debian это простой сценарий оболочки POSIX, который ищет команды в$PATH
.busybox
также естьwhich
команда.Существует,
GNU
which
пожалуй, самый экстравагантный. Он пытается распространить действиеwhich
сценария csh на другие оболочки: вы можете сказать ему, каковы ваши псевдонимы и функции, чтобы он мог дать вам лучший ответ (и я полагаю, что некоторые дистрибутивы Linux устанавливают некоторые глобальные псевдонимы дляbash
этого) ,zsh
имеет несколько операторов для расширения до пути исполняемых файлов: оператор=
расширения имени файла и:c
модификатор расширения истории (здесь применяется к расширению параметра ):zsh
Вzsh/parameters
модуле также вносится команда хэш-таблицы в качествеcommands
ассоциативного массива:whatis
Утилита (для одного в оболочке или плане 9 Unix V8 Bourne , кромеrc
/es
) на самом деле не связана , как это только для документации (базы данных отбирает Whatis, то есть человек , страница синопсис).whereis
Он также был добавлен в3BSD
то же время, какwhich
если бы он был написанC
, но неcsh
используется для одновременного поиска исполняемого файла, справочной страницы и исходного кода, но не на основе текущей среды. Итак, еще раз, это отвечает другой необходимости.Теперь, на стандартном фронте, POSIX определяет
command -v
и-V
команды (которые используются, чтобы быть необязательным до POSIX.2008). UNIX определяетtype
команду (без опции). Это все (where
,which
,whence
не указаны в любом стандарте)До некоторой версии,
type
иcommand -v
были необязательными в спецификации Linux Standard Base, которая объясняет, почему, например, некоторые старые версииposh
(хотя и основанные наpdksh
которых имели обе) не имели ни того, ни другого.command -v
также был добавлен в некоторые реализации оболочки Bourne (например, в Solaris).Статус сегодня
В настоящее время статус таков
type
иcommand -v
вездесущ во всех оболочках, похожих на Bourne (хотя, как отмечает @jarno, обратите внимание на caveat / bug,bash
когда он не в режиме POSIX или некоторые потомки оболочки Almquist ниже в комментариях).tcsh
это единственная оболочка, которую вы хотели бы использоватьwhich
(поскольку ее там нетtype
иwhich
она встроена).В других , чем оболочках
tcsh
иzsh
,which
может сказать вам путь данного исполняемого файла, пока нет псевдонима или функции к тому же имени в любом из наших~/.cshrc
,~/.bashrc
или любого другого файла запуск оболочки и не определить$PATH
в вашем~/.cshrc
. Если у вас есть псевдоним или функция, определенная для него, он может или не может сказать вам об этом, или сказать вам неправильную вещь.Если вы хотите знать обо всех командах с заданным именем, ничего переносимого нет. Вы можете использовать
where
вtcsh
илиzsh
,type -a
вbash
илиzsh
,whence -a
в ksh93 и в других оболочках, которые вы можете использоватьtype
в сочетании сwhich -a
которым может работать.рекомендации
Получение пути к исполняемому файлу
Теперь, чтобы получить путь к исполняемому файлу в скрипте, есть несколько предостережений:
был бы стандартный способ сделать это.
Однако есть несколько проблем:
type
,which
,command -v
... все используют эвристики , чтобы узнать путь. Они перебирают$PATH
компоненты и находят первый не каталогный файл, для которого у вас есть разрешение на выполнение. Однако, в зависимости от оболочки, когда дело доходит до выполнения команды, многие из них (Bourne, AT & T ksh, zsh, ash ...) будут просто выполнять их в порядке,$PATH
покаexecve
системный вызов не вернется с ошибкой , Например, если$PATH
содержится/foo:/bar
и вы хотите выполнитьls
, они сначала будут пытаться выполнить,/foo/ls
или если это не удается/bar/ls
. Сейчас исполнение/foo/ls
может произойти сбой, потому что у вас нет разрешения на выполнение, но и по многим другим причинам, например, это не допустимый исполняемый файл.command -v ls
сообщит,/foo/ls
если у вас есть разрешение на выполнение/foo/ls
, но запускls
может фактически выполняться,/bar/ls
если/foo/ls
он не является допустимым исполняемым файлом.foo
является встроенной функцией или функцией или псевдонимом,command -v foo
возвращаетfoo
. С некоторыми оболочками, такими какash
,pdksh
илиzsh
, он также может возвращать,foo
если$PATH
включает пустую строку иfoo
в текущем каталоге есть исполняемый файл. Есть некоторые обстоятельства, когда вам может понадобиться принять это во внимание. Имейте в виду, например, что список встроенных функций зависит от реализации оболочки (например,mount
иногда встроен для busyboxsh
) и, например,bash
может получать функции из среды.$PATH
содержит компоненты относительного пути (обычно.
или пустую строку, которые оба ссылаются на текущий каталог, но могут быть чем угодно), в зависимости от оболочки,command -v cmd
может не выводиться абсолютный путь. Таким образом, путь, который вы получите в то время, когда вы бежитеcommand -v
, больше не будет действительным после васcd
где-то еще./opt/ast/bin
(хотя точный путь может варьироваться в разных системах , я считаю) в вас$PATH
, ksh93 будет предоставлять несколько дополнительных встроенных команд (chmod
,cmp
,cat
...), ноcommand -v chmod
вернется ,/opt/ast/bin/chmod
даже если этот путь Безразлично» не существует.Определение, существует ли команда
Чтобы узнать, существует ли данная команда стандартно, вы можете сделать:
Где можно использовать
which
(t)csh
В
csh
и уtcsh
вас нет большого выбора. Вtcsh
, это нормально, какwhich
встроено. Во- первыхcsh
, это будет системнаяwhich
команда, которая в некоторых случаях может не выполнять то, что вы хотите.найти команды только в некоторых оболочках
Случай , когда это возможно , имеет смысл использовать
which
, если вы хотите знать , путь команды, игнорируя потенциальные внутренние команды или функции оболочки вbash
,csh
(неtcsh
),dash
илиBourne
сценарии оболочки, то есть снаряды , которые не имеютwhence -p
(например ,ksh
илиzsh
) ,command -ev
(likeyash
),whatis -p
(rc
,akanga
) или встроенныйwhich
(liketcsh
илиzsh
) в системах, гдеwhich
доступен и не являетсяcsh
сценарием.Если эти условия соблюдены, то:
даст вам путь к первому
echo
входу$PATH
(за исключением угловых случаев), независимо от того, является лиecho
также встроенная оболочка / псевдоним / функция или нет.В других оболочках вы бы предпочли:
echo==echo
илиecho=$commands[echo]
илиecho=${${:-echo}:c}
echo=$(whence -p echo)
echo=$(command -ev echo)
echo=`whatis -p echo`
(остерегайтесь путей с пробелами)set echo (type -fp echo)
Обратите внимание, что если все, что вы хотите сделать, это запустить эту
echo
команду, вам не нужно указывать ее путь, вы можете просто сделать:Например, с помощью
tcsh
, чтобы предотвратить использование встроенной функцииwhich
:когда вам нужна внешняя команда
Другой случай, когда вы можете захотеть использовать
which
это когда вам действительно нужна внешняя команда. POSIX требует, чтобы все встроенные функции оболочки (напримерcommand
) также были доступны как внешние команды, но, к сожалению, это не так воcommand
многих системах. Например, редко можно найтиcommand
команду в операционных системах на основе Linux, в то время как у большинства из них естьwhich
команда (хотя разные с разными параметрами и поведением).Случаи, когда вам может понадобиться внешняя команда, будут выполняться там, где вы будете выполнять команду без вызова оболочки POSIX.
system("some command line")
,popen()
... функции C или различных языках действительно вызвать оболочку для разбора этой командной строки, так чтоsystem("command -v my-cmd")
работают в них. Исключением является то,perl
что оптимизируется оболочка, если она не видит никаких специальных символов оболочки (кроме пробела). Это также относится к его оператору обратного вызова:Добавление
:;
вышеупомянутого заставляетperl
вызывать там оболочку. Используяwhich
, вам не придется использовать этот трюк.источник
which
этоcsh
скрипт для многих коммерческих Unices. Причина историческая, поэтому я дал историю, чтобы люди понимали, откуда она взялась, почему люди привыкли использовать ее и почему на самом деле нет причин, по которым вы должны ее использовать. И да, некоторые люди используют (t) csh. Еще не все используют Linuxwhich
, в отличие от того, что вы пытаетесь использоватьwhich
, историюwhich
, реализацииwhich
, другие команды для выполнения связанных задач или причины для фактического использованияwhich
? Почему другие команды лучше ? Чем они отличаются отwhich
? Как они избегают его ловушек? Этот ответ на самом деле тратит больше слов на проблемы с альтернативами, чем проблемы сwhich
.command -v
не проверяет разрешение на выполнение, по крайней мере, если вы вызываете его с помощью аргумента чистого имени файла без пути. Я протестировал dash 0.5.8 и GNU bash 4.3.48.touch /usr/bin/mytestfile
а затем запускаюcommand -v mytestfile
, он даст путь (тогда какwhich mytestfile
нет).bash
остановится на неисполняемом файле, если он не сможет найти исполняемый файл, так что это «ОК» (хотя на практике можно было быcommand -v
/type
вернуть ошибку), так как это команда, которую он попытается выполнить при запускеmytestfile
, ноdash
поведение глючит, так как если есть неисполняемый файлcmd
перед исполняемым,command -v
возвращает неисполняемый, в то время как выполнениеcmd
будет исполнять исполняемый (неправильный также хэшируется). FreeBSDsh
(также основанная наash
) имеет ту же ошибку. zsh, yash, ksh, mksh, bash as sh в порядке.Причины, по которым кто-то может не захотеть использовать
which
, уже были объяснены, но вот несколько примеров на нескольких системах, где наwhich
самом деле происходит сбой.В оболочках типа Bourne мы сравниваем выходные данные
which
с выходными даннымиtype
(type
будучи встроенной в оболочку, она должна быть основной истиной, поскольку это оболочка, говорящая нам, как она будет вызывать команду).Многие случаи являются угловыми , но имейте в виду, что
which
/type
часто используются в угловых случаях (чтобы найти ответ на неожиданное поведение, например: почему, черт возьми, эта команда ведет себя так, какую я вызываю? ).Большинство систем, большинство Bourne-подобных оболочек: функции
Наиболее очевидный случай для функций:
Причина в том, что
which
только отчеты об исполняемых файлах, а иногда и о псевдонимах (хотя и не всегда в вашей оболочке), а не о функциях.GNU, на которой man-страница имеет неработающий (как они забыли процитировать
$@
) пример того, как использовать ее и для отчета о функциях, но так же, как и для псевдонимов, потому что она не реализует синтаксический анализатор оболочки, ее легко обмануть:Большинство систем, большинство Bourne-подобных оболочек: встроенные
Другой очевидный случай или ключевые слова встроенных функций , как и
which
быть внешней командой не имеет возможностей знать , какие встроенные функции вашей оболочки есть (и некоторые оболочки , какzsh
,bash
илиksh
могут загружать динамически встроенные команды):(это не относится к тому,
zsh
гдеwhich
встроен)Solaris 10, AIX 7.1, HP / UX 11i, Tru64 5.1 и многие другие:
Это потому, что в большинстве коммерческих Unices
which
(как в оригинальной реализации на 3BSD) естьcsh
скрипт, который читает~/.cshrc
. Псевдонимы, о которых он сообщит, определены там, независимо от того, какие псевдонимы вы определили в данный момент, и независимо от того, какую оболочку вы используете.В HP / UX или Tru64:
(версии Solaris и AIX исправили эту проблему, сохранив
$path
перед чтением~/.cshrc
и восстановив его перед поиском команд (ы))Или же:
(конечно, будучи
csh
сценарием, нельзя ожидать, что он будет работать с аргументами, содержащими пробелы ...)CentOS 6.4, bash
В этой системе существует общесистемный псевдоним, заключающий в себе
which
команду GNU .Фиктивный выход , потому что
which
читает выводbash
«с ,alias
но не знает , как разобрать его должным образом и использует эвристические методы (один псевдоним в строку, ищет первый найденную команду после того, как|
,;
,&
...)Хуже всего то, что в CentOS
zsh
есть прекрасноwhich
встроенная команда, но CentOS удалось ее сломать, заменив ее нерабочим псевдонимом в GNUwhich
.Debian 7.0, ksh93:
(хотя относится к большинству систем с множеством оболочек)
На Debian
/bin/which
есть/bin/sh
скрипт. В моем случаеsh
бытие,dash
но это то же самое, когда этоbash
.Unset
PATH
неPATH
означает отключение поиска, а означает использование системного 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
(да, сначала просматривает текущий каталог! )).Именно поэтому
which
получает это неправильно выше , так как он используетdash
« по умолчанию s ,PATH
которое отличается отksh93
» SЭто не лучше с GNU,
which
который сообщает:(интересно, действительно есть
/usr/local/bin/which
в моей системе , которая на самом деле являетсяakanga
сценарий , который пришел сakanga
(сrc
производной оболочки , где по умолчаниюPATH
является/usr/ucb:/usr/bin:/bin:.
))Баш, любая система:
Тот, на кого ссылается Крис в своем ответе :
Также после звонка
hash
вручную:Теперь случай, когда
which
и иногдаtype
не получаетсяТеперь с некоторыми снарядами:
С другими:
Ни заранее,
which
ниtype
может не знать, чтоb/foo
не может быть исполнено. Некоторые оболочки , какbash
,ksh
илиyash
, при вызовеfoo
будет действительно попытаться запуститьb/foo
и сообщить об ошибке, в то время как другие (какzsh
,ash
,csh
,Bourne
,tcsh
) будет работатьa/foo
на провалexecve()
системного вызова наb/foo
.источник
mksh
фактически использует что-то другое для значения по умолчанию$PATH
: сначала_PATH_DEFPATH
используется константа времени компиляции операционной системы (чаще всего на BSD), затемconfstr(_CS_PATH, …)
используется (POSIX), и, если оба не существуют или не работают,/bin:/usr/bin:/sbin:/usr/sbin
используется.ls
это функция, которую она используетls
из PATH. Иwhich
хорошо, чтобы сказать вам, какой из них используется/usr/bin/ls
или/usr/local/bin/ls
. Я не вижу «Почему бы не использовать какой» ....which ls
даст мне ,/bin/ls
независимо от того ,ls
не вызывает функцию/bin/ls
или/opt/gnu/bin/ls
илиdir
или вообще ничего. IOW,which
(то, что реализации, IMMV) дает что-то неуместноеls
функция. Я знаю , что мояls
функция вызоваls
изPATH
. Теперьwhich
говорит мне, где файл. Вы видите только один вариант использования: «Что бы моя оболочка сделала с этой командой». Для этого случая использованияwhich
это неправильно, правильно. Но есть и другие случаи использования, где (GNU)which
- это абсолютно правильно.which
реализации. Кто-то скажет вам, что это псевдоним (если у вас настроен псевдоним или если~/.cshrc
в вашем доме есть такой псевдоним), кто-то даст вам путь, но неправильный при некоторых условиях.sh -c 'command -v ls'
хотя он и не идеален, он все же с большей вероятностью даст вам правильный ответ на это другое требование (а также является стандартным).Одна вещь, которую (из моего быстрого бега) кажется, что Стефан не упомянул, это то, что
which
он не имеет представления о хеш-таблице пути вашей оболочки. Это приводит к тому, что он может возвращать результат, который не отражает того, что на самом деле выполняется, что делает его неэффективным при отладке.источник
В UNIX духе: сделать каждую программу сделать одну вещь хорошо.
Если цель состоит в том, чтобы ответить: какой исполняемый файл существует с этим именем?
Какая исполняемая программа, поставляемая с системами Debian, является хорошим ответом. Предоставленные csh включали псевдонимы, что является источником проблем. То, что некоторые оболочки предоставляют в качестве внутреннего встроенного объекта, имеет другую цель. Либо используйте этот исполняемый файл, либо используйте скрипт, приведенный в конце этого ответа.
Если этот скрипт используется, он отвечает просто, просто и полезно.
Эта цель будет соответствовать первому предложению вашего вопроса:
Если у вас есть система, в которой нет исполняемого файла, который называется (в большинстве систем linux есть), вы можете создать его
~/bin/which
ранее/bin/
в PATH, поэтому личные исполняемые файлы переопределяют системные, такие как в нижней части этого поста:Этот исполняемый файл будет перечислять (по умолчанию) все исполняемые файлы, найденные в PATH. Если требуется только первое, опция
-f
доступна.На данный момент мы попадаем в другую цель:
что будет выполнять оболочка (после разбора)
Это вытекает из вашего второго предложения:
Этот второй предмет пытается найти хороший ответ на вопрос, на который довольно сложно ответить. Оболочки имеют различные взгляды, угловые случаи и (как минимум) различные интерпретации. Добавление к этому:
И конечно, все попытки соответствуют этой цели.
Избегать чего?
Интересно: почему это должно быть сказано, если
which
работает нормально (по крайней мере, в Debian)?В духе UNIX: заставьте каждую программу делать что-то хорошо.
Внешняя программа
which
делает одну вещь: Найти первый исполняемый на пути , который имеет такое же имя , как имя команды . И делает это достаточно хорошо.Я не знаю ни одной другой программы или утилиты, которые бы ответили на этот вопрос более фундаментально. Как таковой, он полезен и может быть использован при необходимости.
Ближайшая альтернатива, кажется,:
command -pv commandName
, но это также сообщит о встроенных и псевдонимах. Не тот же ответ.Конечно,
which
он ограничен, он не отвечает на все вопросы, никакой инструмент не может этого сделать (ну, пока нет ...). Но это полезно, когда используется для ответа на вопрос, на который он был разработан (тот, что выше). Многое вродеed
было ограничено и затемsed
появилось (илиvi
/vim
). Или, какawk
было ограничено, Perl появился и расширился. Тем не менее,ed
,sed
или / иawk
имеют конкретные случаи использования , гдеvim
иperl
являются не лучшими инструментами.Возможно, потому что
which
отвечает только на часть вопроса, который может задать пользователь оболочки:Что выполняется, когда я набираю commandName?
Внешний, который
Который должен быть доступен (во многих системах) как внешний исполняемый файл.
Единственный верный способ вызвать этот внешний инструмент - использовать env, чтобы выйти из оболочки, а затем вызвать
which
(что работает во всех оболочках):Или используйте полный путь к
which
(который может различаться в разных системах):Зачем это
hack
нужно? Потому что некоторые оболочки (особенно zsh) скрываютwhich
:Быть внешним инструментом (вроде
env
) прекрасно объясняет, почему он не будет сообщать внутреннюю информацию оболочки. Как псевдонимы, функции, встроенные функции, специальные встроенные функции, переменные оболочки (не экспортируемые) и т. Д .:Пустой вывод
ll
(общий псевдоним дляll='ls -l'
) указывает на то, чтоll
он не связан с исполняемой программой или, по крайней мере, отсутствует исполняемый файл с именемll
в переменной PATH. Использованиеll
должно вызывать что-то еще, в этом случае, псевдоним:type
а такжеcommand
Команды
type
иcommand -v
запрашиваются POSIX. Ожидается, что они будут работать в большинстве оболочек, и они работают, кроме как в csh, tcsh, fish и rc.Обе команды могут быть использованы для предоставления другой точки зрения, какая команда будет выполнена.
whence
,where
,whereis
,whatis
,hash
Тогда, есть
whence
,where
,whereis
,whatis
,hash
, и некоторые другие. Все разные ответы на похожие вопросы. Все работают по-разному в разных оболочках. Наверное,whence
самый распространенный послеtype
. Другие представляют собой специальные решения, которые по-разному отвечают на один и тот же вопрос.Вероятно ,
which
первый , чтобы знать , если существует исполняемый файл по имени Имя_команды , затемtype
иcommand
затем, если Имя_команды не были найдены еще:whence
,where
,whereis
,whatis
,hash
в таком порядке.Сценарий оболочки для предоставления
which
исполняемого файла.источник
Я никогда не слышал этого. Пожалуйста, приведите конкретные примеры. Я бы побеспокоился о вашем дистрибутиве linux и установленных пакетах программ, так как это откуда
which
!SLES 11,4 x86-64
в версии tcsh 6.18.01:
в bash версии 3.2-147:
which
является частью util-linux стандартного пакета, распространяемого Организацией ядра Linux для использования в составе операционной системы Linux. Он также предоставляет эти другие файлымоя
util-linux
версия 2.19. Примечания к выпуску можно легко найти до версии v2.13 от 28 августа 2007 года. Не уверен, в чем смысл или цель этого, конечно, это не было ответа в этой длинной вещи, проголосовавшей 331 раз.источник
which -v
показываете, это GNU, который (экстравагантный, упомянутый в другом ответе и никоим образом не специфичный для Linux), а не util-linux, который AFAIK никогда не включал в себяwhich
утилиту. util-linux 2.19 с 2011 года, GNU с 2.19 с 2008 года.