"welche", aber alle

19

Ich denke, die meisten kennen den whichBefehl und ich benutze ihn häufig. Ich bin gerade in eine Situation geraten, in der ich neugierig bin, nicht nur welcher Befehl zuerst in meinem Pfad ist, sondern wie viele und wo alle Befehle in all meinen Pfaden sind. Ich habe versucht, auf welcher Manpage (Eingabe man whichhat mich zum Lachen gebracht), aber nichts gesehen.

kenny
quelle
1
Auf meinem System, es ist das erste , was auf der man - Seite aufgelistet: which --all.
Shawn J. Goff
2
Auf meinem (Linux) ist es nur which -a.
Benutzer unbekannt

Antworten:

23

Bei einigen Systemen werden which -aalle Übereinstimmungen angezeigt. Wenn Ihre Shell bash oder zsh¹ ist, können Sie typestattdessen Folgendes verwenden : type fooZeigt die erste Übereinstimmung und type -a foozeigt alle Übereinstimmungen an. Die drei Befehle type, whichund whencetun meist die gleiche Sache; Sie unterscheiden sich zwischen Shells und Betriebssystemen in der Verfügbarkeit, den Optionen und dem, was sie genau melden. typeist immer verfügbar und zeigt alle möglichen befehlsähnlichen Namen an (Aliase, Schlüsselwörter, integrierte Shell-Funktionen und externe Befehle).

Die einzige vollständig portable Möglichkeit, alle Übereinstimmungen anzuzeigen, besteht darin, sich $PATHselbst zu analysieren . Hier ist ein Shell-Skript, das dies ausführt. Wenn Sie es sich um eine Shell - Funktion machen, stellen Sie sicher , dass die Funktion Körper in Klammern einzuschließen (so dass die Änderung IFSund set -fdie Funktion nicht entgehen) und Änderung exitzu 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

¹ Oder ksh 93, laut Dokumentation, obwohl ksh 93s + 2008-01-31 nur die erste Übereinstimmung druckt, wenn ich es versuche.

Gilles 'SO - hör auf böse zu sein'
quelle
Dieser shCode funktioniert nicht richtig, wenn leere Komponenten enthalten sind $PATH. Beachten Sie auch , dass $IFSein Feld - Trennzeichen (in POSIX shells mindestens) , während in der $PATH, Kolon als ein Feld verwendet wird Separator . whichEine korrekte Implementierung finden Sie im Skript unter Debian.
Stéphane Chazelas
das typeeingebaute ksh93u+ 2012-08-01scheint richtig zu funktionieren.
Stéphane Chazelas
5

Das Flag --all oder -a zeigt Ihnen alle Übereinstimmungen in Ihrem Pfad und Aliase (zumindest unter Fedora, Ubuntu und CentOS):

which -a which

Unter AIX und Solaris erhalten Sie folgende Informationen:

echo "$PATH" | sed -e 's/:/ /g' | \
while read -r p; do find "$p" -type f -name "which"; done
Eli Heady
quelle
Sie benötigen doppelte Anführungszeichen um Parameterersetzungen. Andernfalls funktioniert das Skript nicht, wenn $PATHLeerzeichen oder Shell-Globbing-Zeichen enthalten sind. read -rist notwendig, um mit Backslashes fertig zu werden. Dies ist keine gute Methode, da finddies viel Zeit in $PATHAnspruch nimmt und möglicherweise falsche Übereinstimmungen zurückgibt, wenn ein Verzeichnis in Unterverzeichnissen enthält. Zum Glück findist hier nicht nützlich; Siehe meine Antwort.
Gilles 'SO - hör auf böse zu sein'
Ich wusste, dass sich find falsch anfühlte, da es in verschachtelten Verzeichnissen mit Sicherheit langsam sein würde. Globbing und Leerzeichen in $ PATH? eww. Aber Sie haben Recht (obwohl Sie nett genug waren, nicht so viel zu sagen): Mein Einzeiler war schlecht geschrieben.
Eli Heady
1

Wenn Sie keine whichUnterstützung -ahaben oder whenceverfügbar sind, rollen Sie Ihre eigenen:

#!/bin/sh -f

IFS=":"
for PART in $PATH
do
  if test -x "$PART/$1"
  then
    echo $PART/$1
  fi
done
MattBianco
quelle
Es fehlt Ihnen set -f, um das Globbing auf dem ungeschützten Computer zu deaktivieren $PATH. test -fist nicht ausreichend, da hier nur ausführbare Dateien gesucht werden; du brauchst test -x. Hmm, mir ist klar, dass ich den regulären Dateitest in meinem Skript vergessen habe.
Gilles 'SO- hör auf böse zu sein'
@Gilles: nach deinen tipps bearbeitet. Ich bin alle für die Richtigkeit, aber ich finde whence README.txtso unwahrscheinlich wie whence "file* wi?h we!rd name". Ich versuche nur zu zeigen, wie einfach das Überqueren ist $PATH.
MattBianco
0

ksh und zsh haben "wherece" als Shell eingebaut. whence -amacht was du willst unter zsh:

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

Ich muss PATH in zsh bereinigen, ich habe viele Duplikate darin. whence -afunktioniert anders unter ksh:

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

Ich muss sagen, das scheint auch ein potenziell nützliches Verhalten zu sein.

Bruce Ediger
quelle