`yang`, tapi semua

19

Saya pikir sebagian besar akrab dengan whichperintah, dan saya sering menggunakannya. Saya hanya mengalami situasi di mana saya ingin tahu bukan hanya perintah mana yang pertama kali berada di jalur saya, tetapi berapa banyak dan di mana semua perintah di semua jalur saya. Saya mencoba halaman manual mana (mengetik man whichmembuat saya tertawa), tetapi tidak melihat apa-apa.

kenny
sumber
1
Pada sistem saya, itu hal pertama yang tercantum pada halaman man: which --all.
Shawn J. Goff
2
Di tambang (linux) itu saja which -a.
pengguna tidak dikenal

Jawaban:

23

Pada beberapa sistem, which -atampilkan semua kecocokan. Jika shell Anda adalah bash atau zsh¹, Anda dapat menggunakan typesebagai gantinya: type foomenunjukkan kecocokan pertama dan type -a foomenampilkan semua kecocokan. Tiga perintah type, whichdan whencesebagian besar melakukan hal yang sama; mereka berbeda antara cangkang dan sistem operasi dalam ketersediaan, opsi, dan apa yang sebenarnya mereka laporkan. typeselalu tersedia dan menampilkan semua kemungkinan nama seperti perintah (alias, kata kunci, built-in shell, fungsi, dan perintah eksternal).

Satu-satunya cara yang sepenuhnya portabel untuk menampilkan semua pertandingan adalah mengurai $PATHsendiri. Inilah skrip shell yang melakukan ini. Jika Anda menjadikannya fungsi shell, pastikan untuk melampirkan badan fungsi di dalam tanda kurung (sehingga perubahan ke IFSdan set -ftidak keluar dari fungsi), dan ubah exitke 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

¹ Atau ksh 93, menurut dokumentasi, meskipun ksh 93s + 2008-01-31 hanya mencetak kecocokan pertama ketika saya mencoba.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Itu shkode tidak bekerja dengan benar jika ada komponen yang kosong di $PATH. Perhatikan juga bahwa pembatas$IFS bidang (setidaknya dalam POSIX shells) saat dalam , titik dua digunakan sebagai pemisah bidang . Lihat skrip yang ditemukan di Debian untuk implementasi yang benar. $PATHwhich
Stéphane Chazelas
yang typebuiltin di ksh93u+ 2012-08-01tampaknya bekerja dengan baik.
Stéphane Chazelas
5

Bendera --all atau -a akan menampilkan semua kecocokan di jalur Anda, dan alias (setidaknya di Fedora, Ubuntu, dan CentOS):

which -a which

Pada AIX dan Solaris, ini akan membuat Anda lebih dekat:

echo "$PATH" | sed -e 's/:/ /g' | \
while read -r p; do find "$p" -type f -name "which"; done
Eli Heady
sumber
Anda perlu tanda kutip ganda di sekitar penggantian parameter, jika tidak skrip tidak akan berfungsi jika $PATHberisi karakter whitespace atau shell globbing. read -rdiperlukan untuk mengatasi backslash. Ini bukan metode yang baik karena findakan memakan waktu lama dan dapat mengembalikan kecocokan palsu jika direktori di $PATHberisi subdirektori. Untungnya, findtidak berguna di sini; lihat jawaban saya.
Gilles 'SO- stop being evil'
Saya tahu merasa salah karena itu pasti akan lambat di direktori bersarang. Globbing dan spasi dalam $ PATH? baru Tapi Anda benar (walaupun Anda cukup baik untuk tidak banyak bicara): liner saya ditulis dengan buruk.
Eli Heady
1

Jika Anda tidak memiliki whichpendukung -a, atau whencetersedia, gulung sendiri:

#!/bin/sh -f

IFS=":"
for PART in $PATH
do
  if test -x "$PART/$1"
  then
    echo $PART/$1
  fi
done
MattBianco
sumber
Anda tidak ada set -funtuk mematikan globbing pada yang tidak dilindungi $PATH. test -ftidak cukup karena hanya file yang dapat dieksekusi yang diinginkan di sini; kamu membutuhkan test -x. Hmm, saya sadar saya lupa tes file biasa dalam skrip saya.
Gilles 'SO- berhenti bersikap jahat'
@Gilles: diedit sesuai kiat Anda. Saya semua untuk kebenaran, tetapi saya menemukan whence README.txttidak mungkin whence "file* wi?h we!rd name". Hanya berusaha menunjukkan betapa mudahnya untuk melintasi $PATH.
MattBianco
0

ksh dan zsh memiliki "whence" sebagai shell built-in. whence -amelakukan apa yang Anda inginkan di bawah zsh:

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

Saya harus membersihkan PATH di zsh, saya punya banyak duplikat di dalamnya. whence -abekerja secara berbeda di bawah ksh:

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

Saya harus mengatakan, itu sepertinya perilaku yang berpotensi berguna juga.

Bruce Ediger
sumber