„które”, ale wszystkie

19

Myślę, że większość zna whichkomendę i używam jej często. Właśnie natknąłem się na sytuację, w której jestem ciekawy nie tylko, które polecenie jest pierwsze na mojej ścieżce, ale ile i gdzie znajdują się wszystkie polecenia na wszystkich moich ścieżkach. Próbowałem strony man (pisanie na klawiaturze man whichrozśmieszyło mnie), ale nic nie widziałem.

Kenny
źródło
1
W moim systemie, to pierwszą rzeczą, wymienione na stronie mężczyzny: which --all.
Shawn J. Goff
2
Na moim (Linux) to tylko which -a.
użytkownik nieznany

Odpowiedzi:

23

W niektórych systemach which -apokazuje wszystkie dopasowania. Jeśli twoją powłoką jest bash lub zsh¹, możesz typezamiast tego użyć : type foopokazuje pierwsze dopasowanie i type -a foopokazuje wszystkie dopasowania. Te trzy komendy type, whichi whencezrobić głównie to samo; różnią się między powłokami i systemami operacyjnymi pod względem dostępności, opcji i tego, co dokładnie zgłaszają. typejest zawsze dostępne i pokazuje wszystkie możliwe nazwy podobne do poleceń (aliasy, słowa kluczowe, wbudowane powłoki, funkcje i polecenia zewnętrzne).

Jedynym w pełni przenośnym sposobem wyświetlania wszystkich dopasowań jest parsowanie $PATHsiebie. Oto skrypt powłoki, który to robi. Jeśli uczynisz ją funkcją powłoki, pamiętaj o umieszczeniu ciała funkcji w nawiasach (aby zmiana na funkcję IFSi set -fnie ucieczka przed nią), i zmień exitna 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

¹ Lub ksh 93, zgodnie z dokumentacją, chociaż ksh 93s + 2008-01-31 drukuje tylko pierwsze dopasowanie, gdy próbuję.

Gilles „SO- przestań być zły”
źródło
Ten shkod nie działa poprawnie, jeśli są w nim puste komponenty $PATH. Zauważ też, że $IFSjest to separator pól (przynajmniej w powłokach POSIX), podczas gdy w $PATH, dwukropek jest używany jako separator pól . Zobacz whichskrypt znaleziony w Debianie dla poprawnej implementacji.
Stéphane Chazelas,
typewbudowane w ksh93u+ 2012-08-01wydaje się działać poprawnie.
Stéphane Chazelas,
5

Flaga --all lub -a pokaże wszystkie dopasowania na twojej ścieżce oraz aliasy (przynajmniej w Fedorze, Ubuntu i CentOS):

which -a which

W systemach AIX i Solaris zbliżysz się do:

echo "$PATH" | sed -e 's/:/ /g' | \
while read -r p; do find "$p" -type f -name "which"; done
Eli Heady
źródło
Potrzebne są podwójne cudzysłowy wokół podstawień parametrów, w przeciwnym razie skrypt nie będzie działał, jeśli będzie $PATHzawierał spacje lub znaki globowania powłoki. read -rjest konieczne, aby poradzić sobie z odwrotnymi ukośnikami. To nie jest dobra metoda, ponieważ findzajmie to dużo czasu i może zwrócić fałszywe dopasowania, jeśli katalog w $PATHzawiera podkatalogi. Na szczęście findnie przydaje się tutaj; zobacz moją odpowiedź.
Gilles „SO- przestań być zły”
Wiedziałem, że znajdź się źle, ponieważ z pewnością będzie wolna w zagnieżdżonych katalogach. Globbing i spacje w $ PATH? eww. Ale masz rację (chociaż byłeś na tyle miły, żeby nie mówić tak dużo): moja jedna linijka była źle napisana.
Eli Heady
1

Jeśli nie masz whichpomocniczej -alub whencedostępnej, rzuć własną:

#!/bin/sh -f

IFS=":"
for PART in $PATH
do
  if test -x "$PART/$1"
  then
    echo $PART/$1
  fi
done
MattBianco
źródło
Brakuje Ci set -fwyłączenia globowania dla niechronionych $PATH. test -fnie jest wystarczające, ponieważ potrzebne są tutaj tylko pliki wykonywalne; trzeba test -x. Hmm, zdaję sobie sprawę, że zapomniałem o regularnym teście plików w moim skrypcie.
Gilles „SO- przestań być zły”
@Gilles: edytowane zgodnie z Twoimi wskazówkami. Jestem za poprawnością, ale whence README.txtwydaje mi się tak mało prawdopodobne, jak whence "file* wi?h we!rd name". Próbuję tylko pokazać, jak łatwo jest przejść $PATH.
MattBianco
0

ksh i zsh mają wbudowaną powłokę „skąd”. whence -arobi to, co chcesz w Zsh:

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

Muszę wyczyścić PATH w Zsh, mam w nim wiele duplikatów. whence -adziała inaczej pod ksh:

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

Muszę powiedzieć, że to też wydaje się być potencjalnie użytecznym zachowaniem.

Bruce Ediger
źródło