Мне нужно найти путь к данной программе с PATH
помощью сценария оболочки. Путь должен быть фактическим полным путем программы, который может быть передан позже одной из exec*
функций, которая не ищет PATH
саму себя, например execv
.
Существуют такие программы, как kill
, которые доступны как фактическая программа, так и встроенная оболочка одновременно. Если это так, мне нужен полный путь к самой программе.
Существует несколько утилит, которые могут найти программу, PATH
как указано в разделе 2.9.1.1, Поиск команд и выполнение стандарта POSIX .
Существует which
, что не является частью какого-либо стандарта. В некоторых системах это может быть обычная программа, в то время как некоторые оболочки предоставляют ее как встроенную. Кажется, он доступен в большинстве систем и оболочек, но оболочки со встроенной версией также просто возвращают имя встроенной, а не путь к исполняемому файлу. Кроме того, он никак не стандартизирован и может возвращать любой вывод и принимать разные варианты.
bash# which kill
/usr/bin/kill
dash# which kill
/usr/bin/kill
fish# which kill
/usr/bin/kill
mksh# which kill
/usr/bin/kill
tcsh# which kill
kill: shell built-in command.
zsh# which kill
kill: shell built-in command
Существует whence
, который является встроенным из нескольких оболочек. Но не доступно на многих снарядах. Он также вернет имя встроенного вместо пути к программе. A -p
может быть передан, чтобы изменить это поведение.
bash# whence kill
bash: whence: command not found
dash# whence kill
dash: 1: whence: not found
fish# whence kill
fish: Unknown command 'whence'
mksh# whence kill
kill
mksh# whence -p kill
/usr/bin/kill
tcsh# whence kill
whence: Command not found.
zsh# whence kill
kill
zsh# whence -p kill
/usr/bin/kill
Существует command
встроенная функция, указанная в POSIX: 2008 . К сожалению, он также ищет обычные команды и встроенные модули и будет возвращать имя встроенной программы вместо пути к программе, за которой скрывается встроенная команда с тем же именем. Некоторые старые оболочки еще не реализовали это.
bash# command -v kill
kill
dash# command -v kill
kill
fish# command -v kill
/usr/bin/kill
mksh# command -v kill
kill
tcsh# command -v kill
command: Command not found.
zsh# command -v kill
kill
enable
указано ли это в POSIX или нет, но если это так, вы можете использоватьenable -n which
для отключения встроенной оболочки дляwhich
.realpath
enable
предоставлены толькоbash
иzsh
type -p
. И bash, и dash позволяют вам сказатьcommand
команду для запуска реального исполняемого файла, даже если есть функция или встроенная функция с тем же именем.command
пропускает функции (и псевдонимы), но НЕ встроенные, как правильно говорит Q. И вы не всегда можете использовать шебанг, потому что нет пути, по которому можно получить какую-либо оболочку или даже оболочку POSIX во всех системах.Ответы:
Просто найдите это сами.
Испытано в
bash
,dash
,ksh
,mksh
,zsh
Обновить
Вышеприведенное хорошо для отдельного скрипта, однако, если вы планируете встроить его в более крупный скрипт, вы можете использовать что-то более похожее на следующее.
Это объясняется тем , что
IFS
восстанавливается после обнаружения матча, а также поменять местамиexit
«s сreturn
» ыисточник
IFS
переменную? Разве не достаточно иметь этот набор в локальной оболочке? Говоря о местных, будетlocal IFS
портативным? Вышесказанное может плохо взаимодействовать, если что-то еще сохраняет IFS таким же образом. Глядя на этот вопрос на SE ,local
может работать для большинства оболочек, несмотря на то, что не POSIX. Помещение оригинальной версии в(…)
подоболочку может также работать.