`котрий`, але все


19

Я думаю, що більшість знайомих з whichкомандою, і я її часто використовую. Я просто зіткнувся з ситуацією, коли мені цікаво не тільки, яка команда перша на моєму шляху, а скільки і де всі команди на всіх моїх шляхах. Я спробував, яка сторінка людини (введення man whichзмусило мене сміятися), але нічого не побачив.


1
У моїй системі, це перше , що вказані на сторінці людини: which --all.
Шон Дж. Гофф

2
У моєму (Linux) це лише which -a.
користувач невідомий

Відповіді:


23

На деяких системах which -aпоказує всі збіги. Якщо ваша оболонка bash або zsh¹, ви можете використовувати typeзамість цього: type fooпоказує першу відповідність і type -a fooпоказує всі збіги. Три команди type, whichі whenceробити в основному те ж саме; вони відрізняються між оболонками та операційними системами за доступністю, опціями та тим, що саме вони повідомляють. typeзавжди доступний і показує всі можливі імена, подібні до команд (псевдоніми, ключові слова, вбудовані оболонки, функції та зовнішні команди).

Єдиний повністю портативний спосіб відображення всіх матчів - це розібратися $PATH. Ось сценарій оболонки, який робить це. Якщо ви зробите це функцією оболонки, обов'язково укладіть тіло функції в дужки (щоб змінити IFSта set -fне уникнути функції) та змінити exitна return.

#!/bin/sh
set -f       # disable globbing
IFS=:        # break words at : only
not_found=1
for d in $PATH; do
  if [ -f "$d/$x" ] && [ -x "$d/$x" ]; then
    printf '%s\n' "$d/$x"
    not_found=0
  fi
done
exit $not_found

¹ Або ksh 93, згідно з документацією, хоча ksh 93s + 2008-01-31 друкує першу відповідність лише при спробі.


Цей shкод не працює належним чином, якщо в ньому є порожні компоненти $PATH. Також зауважте, що $IFSце роздільник поля (принаймні в оболонках POSIX), а в $PATH, роздільник двокрапки використовується як роздільник поля . Для whichправильної реалізації див. Сценарій, знайдений на Debian.
Stéphane Chazelas

typeвбудований в , ksh93u+ 2012-08-01здається, працює правильно.
Stéphane Chazelas

5

Прапор --all або -a покаже вам всі збіги на вашому шляху та псевдоніми (принаймні на Fedora, Ubuntu та CentOS):

which -a which

На AIX та Solaris це допоможе вам наблизитись:

echo "$PATH" | sed -e 's/:/ /g' | \
while read -r p; do find "$p" -type f -name "which"; done

Вам потрібні подвійні лапки навколо підстановок параметрів, інакше сценарій не буде працювати, якщо $PATHмістить символи пробілу або оболонки з глобальної оболонкою. read -rнеобхідно впоратися з накидами. Це не гарний метод, оскільки findце займе тривалий час і може повернути помилкові збіги, якщо каталог $PATHмістить підкаталоги. На щастя, findтут не корисно; дивіться мою відповідь.
Жил "ТАК - перестань бути злим"

Я знав, що відчуваю себе неправильно, оскільки це, безумовно, буде повільним у вкладених каталогах. Глобінг та пробіли в $ PATH? eww. Але ти маєш рацію (хоча ти був досить приємний, щоб не сказати стільки): мій один лайнер був погано написаний.
Елі Хеді

1

Якщо у вас немає whichпідтримуючої -aабо whenceдоступної, виконайте свої дії:

#!/bin/sh -f

IFS=":"
for PART in $PATH
do
  if test -x "$PART/$1"
  then
    echo $PART/$1
  fi
done

Вам не вистачає, set -fщоб вимкнути глобус на незахищеному $PATH. test -fнедостатньо, оскільки тут потрібні лише виконувані файли; вам потрібно test -x. Хм, я розумію, що забув звичайний тест файлів у своєму сценарії.
Жил "ТАК - перестань бути злим"

@Gilles: редагується відповідно до ваших порад. Я все за коректність, але мені здається whence README.txtтакою ж малоймовірною whence "file* wi?h we!rd name". Просто намагаюся показати, як легко переходити $PATH.
MattBianco

0

ksh і zsh мають "звідки" вбудовану оболонку. whence -aробить те, що ви хочете під zsh:

 7:27AM 7 % whence -a cat
/usr/bin/cat
/bin/cat
/usr/bin/cat
/bin/cat

Мені треба прибрати PATH в zsh, у мене багато дублікатів. whence -aпрацює по-різному під ksh:

$ whence -a cat
cat is a tracked alias for /usr/bin/cat

Я мушу сказати, що це здається також потенційно корисною поведінкою.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.