Ketika mencari jalan untuk dapat dieksekusi atau memeriksa apa yang akan terjadi jika Anda memasukkan nama perintah di shell Unix, ada sejumlah utilitas yang berbeda ( which
, type
, command
, whence
, where
, whereis
, whatis
, hash
, dll).
Kita sering mendengar yang which
harus dihindari. Mengapa? Apa yang harus kita gunakan?
shell
history
which
portability
Stéphane Chazelas
sumber
sumber
which
mengasumsikan konteks shell interaktif. Pertanyaan ini ditandai / mudah dibawa. Jadi saya menafsirkan pertanyaan dalam konteks ini sebagai "apa yang harus digunakan daripadawhich
menemukan executable pertama dari nama yang diberikan dalam$PATH
". Sebagian besar jawaban dan alasan menentangwhich
berurusan dengan alias, bawaan dan fungsi, yang dalam kebanyakan skrip shell portabel di dunia nyata hanya untuk kepentingan akademis. Alias yang didefinisikan secara lokal tidak diwariskan saat menjalankan skrip shell (kecuali jika Anda sumbernya dengan.
).csh
(danwhich
masih berupacsh
skrip pada sebagian besar Unices komersial) tidak dibaca~/.cshrc
saat tidak interaktif. Itu sebabnya Anda akan melihat skrip csh biasanya dimulai dengan#! /bin/csh -f
.which
bukan karena itu bertujuan untuk memberi Anda alias, karena itu dimaksudkan sebagai alat untuk (interaktif) penggunacsh
. Kerang POSIX yang dimiliki penggunacommand -v
.(t)csh
(atau Anda tidak keberatan jika itu tidak memberi Anda hasil yang benar), gunakantype
ataucommand -v
sebagai gantinya . Lihat jawaban untuk alasannya .stat $(which ls)
salah karena beberapa alasan (hilang--
, tanda kutip hilang), tidak hanya penggunaanwhich
). Anda akan menggunakanstat -- "$(command -v ls)"
. Itu mengasumsikanls
memang perintah yang ditemukan pada sistem file (bukan builtin dari shell Anda, atau fungsi alias).which
mungkin memberi Anda jalur yang salah (bukan jalur yang akan dijalankan shell Anda jika Anda memasukkanls
) atau memberi Anda alias seperti yang ditentukan dalam konfigurasi beberapa shell lain ...which
implementasi tidak akan memberi Anda bahkanls
yang akan ditemukan oleh pencarian$PATH
(terlepas dari apa yangls
mungkin diminta dalam shell Anda).sh -c 'command -v ls'
, atauzsh -c 'rpm -q --whatprovides =ls'
lebih mungkin memberi Anda jawaban yang benar. Intinya di sini adalahwhich
warisan yang rusakcsh
.Jawaban:
Inilah semua yang Anda tidak pernah berpikir Anda tidak akan mau tahu tentang hal itu:
Ringkasan
Untuk mendapatkan pathname dari executable dalam skrip shell Bourne-like (ada beberapa peringatan; lihat di bawah):
Untuk mengetahui apakah ada perintah yang diberikan:
Pada prompt shell seperti Bourne interaktif:
The
which
perintah adalah warisan yang rusak dari C-Shell dan lebih baik ditinggalkan sendirian di kerang Bourne-seperti.Gunakan Kasing
Ada perbedaan antara mencari informasi itu sebagai bagian dari skrip atau secara interaktif di prompt shell.
Pada prompt shell, kasus penggunaan yang umum adalah: perintah ini berperilaku aneh, apakah saya menggunakan yang benar? Apa yang sebenarnya terjadi ketika saya mengetik
mycmd
? Bisakah saya melihat lebih jauh apa itu?Dalam hal ini, Anda ingin tahu apa yang dilakukan shell Anda ketika Anda menjalankan perintah tanpa benar-benar menjalankan perintah.
Dalam skrip shell, cenderung sangat berbeda. Dalam skrip shell tidak ada alasan mengapa Anda ingin tahu di mana atau apa perintah itu jika semua yang ingin Anda lakukan adalah menjalankannya. Secara umum, apa yang ingin Anda ketahui adalah jalur yang dapat dieksekusi, sehingga Anda dapat memperoleh lebih banyak informasi darinya (seperti jalur ke file lain terkait dengan itu, atau membaca informasi dari konten file yang dapat dieksekusi di jalur itu).
Interaktif, Anda mungkin ingin tahu tentang semua yang
my-cmd
perintah yang tersedia pada sistem, dalam skrip, jarang jadi.Sebagian besar alat yang tersedia (seperti yang sering terjadi) telah dirancang untuk digunakan secara interaktif.
Sejarah
Sedikit sejarah dulu.
Kerang Unix awal hingga akhir 70-an tidak memiliki fungsi atau alias. Hanya mencari tradisional executable di
$PATH
.csh
memperkenalkan alias sekitar tahun 1978 (meskipuncsh
pertama kali dirilis pada2BSD
bulan Mei 1979), dan juga pemrosesan.cshrc
bagi pengguna untuk menyesuaikan shell (setiap shell, seperti yangcsh
dibaca.cshrc
bahkan ketika tidak interaktif seperti dalam skrip).sementara shell Bourne pertama kali dirilis di Unix V7 pada tahun 1979, dukungan fungsi hanya ditambahkan jauh kemudian (1984 dalam SVR2), dan lagi pula, itu tidak pernah memiliki beberapa
rc
file (.profile
yaitu untuk mengkonfigurasi lingkungan Anda, bukan shell per se ).csh
mendapat jauh lebih populer daripada shell Bourne (meskipun memiliki sintaks yang jauh lebih buruk daripada shell Bourne) itu menambahkan banyak fitur yang lebih nyaman dan menyenangkan untuk penggunaan interaktif.Pada
3BSD
(1980),which
skrip csh ditambahkan bagicsh
pengguna untuk membantu mengidentifikasi sebuah executable, dan skrip ini hampir tidak berbeda dengan yang dapat Anda temukanwhich
di banyak Unix komersial saat ini (seperti Solaris, HP / UX, AIX atau Tru64).Skrip itu membaca pengguna
~/.cshrc
(seperti semuacsh
skrip lakukan kecuali dipanggil dengancsh -f
), dan mencari nama perintah yang disediakan dalam daftar alias dan dalam$path
(array yangcsh
mempertahankan berdasarkan$PATH
).Ini dia,
which
menjadi yang pertama untuk shell paling populer saat itu (dancsh
masih populer sampai pertengahan 90-an), yang merupakan alasan utama mengapa ia didokumentasikan dalam buku dan masih banyak digunakan.Perhatikan bahwa, bahkan untuk
csh
pengguna,which
skrip csh tidak selalu memberi Anda informasi yang benar. Itu mendapatkan alias yang didefinisikan~/.cshrc
, bukan yang Anda mungkin telah didefinisikan nanti pada prompt atau misalnya dengan memasukkan filesource
laincsh
, dan (meskipun itu bukan ide yang baik),PATH
mungkin didefinisikan ulang~/.cshrc
.Menjalankan
which
perintah itu dari shell Bourne, masih akan mencari alias yang didefinisikan di Anda~/.cshrc
, tetapi jika tidak memilikinya karena Anda tidak menggunakannyacsh
, itu mungkin masih memberi Anda jawaban yang benar.Fungsionalitas yang serupa tidak ditambahkan ke shell Bourne hingga 1984 di SVR2 dengan
type
perintah builtin. Fakta bahwa ia dibangun (sebagai lawan dari skrip eksternal) berarti ia dapat memberi Anda informasi yang benar (sampai batas tertentu) karena memiliki akses ke internal shell.type
Perintah awal mengalami masalah yang sama sepertiwhich
skrip yang tidak mengembalikan status keluar kegagalan jika perintah tidak ditemukan. Juga, untuk executable, sebaliknyawhich
, ini menghasilkan sesuatu sepertils is /bin/ls
bukannya/bin/ls
yang membuatnya kurang mudah digunakan dalam skrip.Unix Version 8's (tidak dirilis di wild) Bourne shell telah
type
dibangun ulang namanya menjadiwhatis
. Dan shell Plan9 (penerus Unix yang pernah menjadi) jugarc
(dan turunannya sepertiakanga
danes
)whatis
juga.Shell Korn (subset yang mendasari definisi sh POSIX), dikembangkan pada pertengahan 80-an tetapi tidak banyak tersedia sebelum 1988, menambahkan banyak
csh
fitur (editor baris, alias ...) di atas shell Bourne . Ia menambahkanwhence
builtin -nya sendiri (sebagai tambahantype
) yang mengambil beberapa opsi (-v
untuk menyediakantype
keluaran verbose-like, dan-p
hanya mencari executable (bukan alias / fungsi ...)).Bersamaan dengan kekacauan terkait dengan masalah hak cipta antara AT&T dan Berkeley, beberapa implementasi perangkat lunak shell gratis muncul di akhir tahun 80-an awal tahun 90-an. Semua shell Almquist (abu, untuk menjadi pengganti shell Bourne di BSD), implementasi domain publik ksh (pdksh),
bash
(disponsori oleh FSF),zsh
keluar di antara tahun 1989 dan 1991.Ash, meskipun dimaksudkan sebagai pengganti shell Bourne tidak memiliki
type
builtin sampai jauh kemudian (di NetBSD 1.3 dan FreeBSD 2.3), meskipun sudahhash -v
. OSF / 1/bin/sh
memilikitype
builtin yang selalu mengembalikan 0 hingga OSF / 1 v3.x.bash
tidak menambahkanwhence
tetapi menambahkan-p
opsi untuktype
mencetak jalur (type -p
akan sepertiwhence -p
) dan-a
melaporkan semua perintah yang cocok.tcsh
dibuatwhich
builtin dan menambahkanwhere
perintah bertindak sepertibash
'stype -a
.zsh
memiliki semuanya.The
fish
shell (2005) memilikitype
perintah diimplementasikan sebagai fungsi.The
which
Script csh Sementara itu dihapus dari NetBSD (seperti yang builtin di tcsh dan tidak banyak digunakan dalam kerang lainnya), dan fungsi ditambahkan kewhereis
(ketika dipanggil sebagaiwhich
,whereis
berperilaku sepertiwhich
kecuali bahwa itu hanya mendongak executable di$PATH
). Di OpenBSD dan FreeBSD,which
juga diubah menjadi satu yang ditulis dalam C yang mencari perintah$PATH
saja.Implementasi
Ada lusinan implementasi
which
perintah pada berbagai Unix dengan sintaks dan perilaku yang berbeda.Di Linux (di samping yang builtin di dalam
tcsh
danzsh
) kami menemukan beberapa implementasi. Pada sistem Debian terbaru misalnya, ini adalah skrip shell POSIX sederhana yang mencari perintah di$PATH
.busybox
juga memilikiwhich
perintah.Ada
GNU
which
yang mungkin merupakan yang paling mewah. Ia mencoba untuk memperluas apa yang dilakukanwhich
skrip csh ke shell lain: Anda dapat memberi tahu apa itu alias dan fungsi Anda sehingga dapat memberikan jawaban yang lebih baik (dan saya percaya beberapa distribusi Linux menetapkan beberapa alias global di sekitarnya untukbash
melakukannya) .zsh
memiliki beberapa operator untuk memperluas ke jalur yang dapat dieksekusi: operator=
ekspansi nama file dan:c
pengubah ekspansi riwayat (di sini diterapkan pada ekspansi parameter ):zsh
, dalamzsh/parameters
modul juga membuat tabel hash perintah sebagaicommands
array asosiatif:The
whatis
utilitas (kecuali untuk satu di Unix V8 Bourne shell atau Plan 9rc
/es
) tidak benar-benar terkait seperti itu untuk dokumentasi saja (greps database whatis, yaitu halaman man sinopsis).whereis
juga ditambahkan pada3BSD
saat yang sama seolah-which
olah itu ditulisC
, tidakcsh
dan digunakan untuk mencari pada saat yang sama, halaman buku panduan dan sumber yang dapat dieksekusi tetapi tidak didasarkan pada lingkungan saat ini. Jadi sekali lagi, itu menjawab kebutuhan yang berbeda.Sekarang, di bagian depan standar, POSIX menentukan perintah
command -v
dan-V
(yang dulunya opsional sampai POSIX.2008). UNIX menentukantype
perintah (tidak ada opsi). Itu semua (where
,which
,whence
tidak ditentukan dalam standar apapun)Hingga beberapa versi,
type
dancommand -v
merupakan opsional dalam spesifikasi Pangkalan Linux Standar yang menjelaskan mengapa misalnya beberapa versi lamaposh
(meskipun berdasarkanpdksh
keduanya) tidak memiliki keduanya.command -v
juga ditambahkan ke beberapa implementasi shell Bourne (seperti pada Solaris).Status Hari Ini
Status saat ini adalah bahwa
type
dancommand -v
ada di mana-mana di semua cangkang Bourne-like (meskipun, seperti dicatat oleh @jarno, perhatikan peringatan / bugbash
ketika tidak dalam mode POSIX atau beberapa keturunan cangkang Almquist di bawah ini dalam komentar).tcsh
adalah satu-satunya shell di mana Anda ingin menggunakanwhich
(karena tidaktype
ada danwhich
dibangun).Di dalam shell selain
tcsh
danzsh
,which
dapat memberi tahu Anda jalur executable yang diberikan selama tidak ada alias atau fungsi dengan nama yang sama di salah satu dari kami~/.cshrc
,~/.bashrc
atau file startup shell apa pun dan Anda tidak menentukan$PATH
di~/.cshrc
. Jika Anda memiliki alias atau fungsi yang ditentukan untuknya, itu mungkin atau mungkin tidak memberi tahu Anda tentang hal itu, atau memberi tahu Anda hal yang salah.Jika Anda ingin tahu tentang semua perintah dengan nama yang diberikan, tidak ada yang portabel. Anda akan menggunakan
where
ditcsh
atauzsh
,type -a
dalambash
atauzsh
,whence -a
di ksh93 dan kerang lainnya, Anda dapat menggunakantype
dalam kombinasi denganwhich -a
yang mungkin bekerja.Rekomendasi
Mendapatkan pathname ke executable
Sekarang, untuk mendapatkan pathname dari executable dalam skrip, ada beberapa peringatan:
akan menjadi cara standar untuk melakukannya.
Ada beberapa masalah:
type
,which
,command -v
... semua heuristik digunakan untuk mengetahui jalan. Mereka loop melalui$PATH
komponen dan menemukan file non-direktori pertama yang Anda jalankan izinnya. Namun, tergantung pada shell, ketika menjalankan perintah, banyak dari mereka (Bourne, AT&T ksh, zsh, ash ...) hanya akan menjalankannya dalam urutan$PATH
sampaiexecve
panggilan sistem tidak kembali dengan kesalahan . Misalnya jika$PATH
berisi/foo:/bar
dan Anda ingin mengeksekusils
, mereka akan terlebih dahulu mencoba mengeksekusi/foo/ls
atau jika itu gagal/bar/ls
. Sekarang eksekusi/foo/ls
mungkin gagal karena Anda tidak memiliki izin eksekusi tetapi juga karena banyak alasan lain, seperti itu bukan eksekusi yang valid.command -v ls
akan melaporkan/foo/ls
jika Anda memiliki izin eksekusi/foo/ls
, tetapi menjalankanls
mungkin benar-benar berjalan/bar/ls
jika/foo/ls
bukan merupakan eksekusi yang valid.foo
merupakan builtin atau fungsi atau alias,command -v foo
kembalifoo
. Dengan beberapa shell sepertiash
,pdksh
atauzsh
, ia juga dapat kembalifoo
jika$PATH
menyertakan string kosong dan adafoo
file yang dapat dieksekusi di direktori saat ini. Ada beberapa kondisi di mana Anda mungkin perlu memperhitungkannya. Ingatlah misalnya bahwa daftar bawaan bervariasi dengan implementasi shell (misalnya,mount
kadang-kadang dibangun untuk busyboxsh
), dan misalnyabash
bisa mendapatkan fungsi dari lingkungan.$PATH
berisi komponen path relatif (biasanya.
atau string kosong yang keduanya merujuk ke direktori saat ini tetapi bisa berupa apa saja), tergantung pada shell,command -v cmd
mungkin tidak menampilkan path absolut. Jadi jalur yang Anda dapatkan pada saat Anda menjalankancommand -v
tidak akan lagi berlaku setelah Anda dicd
tempat lain./opt/ast/bin
(meskipun jalan yang tepat dapat bervariasi pada sistem yang berbeda saya percaya) di dalam kamu$PATH
, ksh93 akan membuat tersedia beberapa builtin tambahan (chmod
,cmp
,cat
...), tapicommand -v chmod
akan kembali/opt/ast/bin/chmod
bahkan jika jalan itu doesn' tidak ada.Menentukan apakah ada perintah
Untuk mengetahui apakah perintah yang diberikan ada secara standar, Anda dapat melakukan:
Di mana orang mungkin ingin menggunakan
which
(t)csh
Di
csh
dantcsh
, Anda tidak punya banyak pilihan. Dalamtcsh
, itu bagus sepertiwhich
builtin. Dalamcsh
, itu akan menjadiwhich
perintah sistem , yang mungkin tidak melakukan apa yang Anda inginkan dalam beberapa kasus.temukan perintah hanya di beberapa shell
Suatu kasus di mana masuk akal untuk digunakan
which
adalah jika Anda ingin mengetahui lintasan sebuah perintah, mengabaikan potensi builtin shell atau fungsi dalambash
,csh
(tidaktcsh
)dash
, atauBourne
skrip shell, yaitu shell yang tidak memilikiwhence -p
(sukaksh
atauzsh
) ,command -ev
(sepertiyash
),whatis -p
(rc
,akanga
) atau builtinwhich
(sukatcsh
atauzsh
) pada sistem di manawhich
tersedia dan bukancsh
skrip.Jika persyaratan tersebut dipenuhi, maka:
akan memberikan jalan yang pertama
echo
di$PATH
(kecuali dalam kasus sudut), terlepas dari apakahecho
juga terjadi menjadi shell builtin / alias / fungsi atau tidak.Di shell lain, Anda lebih suka:
echo==echo
atauecho=$commands[echo]
atauecho=${${:-echo}:c}
echo=$(whence -p echo)
echo=$(command -ev echo)
echo=`whatis -p echo`
(waspadalah terhadap jalur dengan spasi)set echo (type -fp echo)
Perhatikan bahwa jika semua yang Anda ingin lakukan adalah menjalankan bahwa
echo
perintah, Anda tidak harus mendapatkan jalan, Anda hanya dapat melakukan:Misalnya, dengan
tcsh
, untuk mencegah builtinwhich
digunakan:ketika Anda membutuhkan perintah eksternal
Kasus lain di mana Anda mungkin ingin menggunakan
which
adalah ketika Anda benar - benar membutuhkan perintah eksternal. POSIX mensyaratkan bahwa semua shell builtin (seperticommand
) juga tersedia sebagai perintah eksternal, tetapi sayangnya itu tidak berlaku untukcommand
banyak sistem. Sebagai contoh, jarang menemukancommand
perintah pada sistem operasi berbasis Linux sementara kebanyakan dari mereka memilikiwhich
perintah (meskipun berbeda dengan opsi dan perilaku yang berbeda).Kasus di mana Anda mungkin menginginkan perintah eksternal berada di mana pun Anda akan menjalankan perintah tanpa menggunakan shell POSIX.
Fungsi
system("some command line")
,popen()
... C atau berbagai bahasa memang memanggil shell untuk mem-parsing baris perintah itu, jadisystem("command -v my-cmd")
kerjakanlah di dalamnya. Pengecualian untuk hal itu adalahperl
yang mengoptimalkan shell jika tidak melihat karakter khusus shell (selain ruang). Itu juga berlaku untuk operator backtick-nya:Penambahan bahwa
:;
kekuatan di atasperl
untuk memanggil shell di sana. Dengan menggunakanwhich
, Anda tidak perlu menggunakan trik itu.sumber
which
adalahcsh
skrip di banyak Unite komersial. Alasannya historis, itu sebabnya saya memberikan sejarah, jadi orang mengerti dari mana asalnya, mengapa orang terbiasa menggunakannya dan mengapa sebenarnya tidak ada alasan Anda harus menggunakannya. Dan ya, beberapa orang menggunakan (t) csh. Belum semua orang menggunakan Linuxwhich
, sebagai lawan dari hal-hal yang mungkin Anda cobawhich
lakukan, sejarahwhich
, implementasiwhich
, perintah lain untuk melakukan tugas terkait, atau alasan untuk benar-benar menggunakanwhich
? Mengapa perintah lain lebih baik ? Apa yang mereka lakukan secara berbedawhich
? Bagaimana mereka menghindari jebakannya? Jawaban ini sebenarnya menghabiskan lebih banyak kata pada masalah dengan alternatif daripada masalah denganwhich
.command -v
tidak memeriksa izin eksekusi, setidaknya jika Anda menyebutnya dengan argumen nama file murni tanpa jalur. Saya menguji dengan dash 0.5.8 dan GNU bash 4.3.48.touch /usr/bin/mytestfile
dan kemudian dijalankancommand -v mytestfile
, itu akan memberikan path (padahalwhich mytestfile
tidak).bash
akan menyelesaikan file yang tidak dapat dieksekusi jika tidak dapat menemukan file yang dapat dieksekusi, jadi itu "OK" (meskipun dalam praktiknya seseorang lebih sukacommand -v
/type
mengembalikan kesalahan) karena itulah perintah yang akan coba dijalankan ketika Anda menjalankanmytestfile
, tetapidash
perilaku buggy, seolah-olah ada yang tidak dapat dieksekusi dicmd
depan yang dapat dieksekusi,command -v
mengembalikan yang tidak dapat dieksekusi sementara mengeksekusicmd
akan mengeksekusi yang dapat dieksekusi (yang salah juga hash). FreeBSDsh
(juga berdasarkanash
) memiliki bug yang sama. zsh, yash, ksh, mksh, bash karena dia OK.Alasan mengapa seseorang mungkin tidak ingin menggunakan
which
sudah dijelaskan, tetapi berikut adalah beberapa contoh pada beberapa sistem di manawhich
sebenarnya gagal.Pada cangkang mirip Bourne, kami membandingkan keluaran
which
dengan keluarantype
(type
menjadi cangkang yang dibangun, itu dimaksudkan sebagai kebenaran dasar, karena cangkang memberi tahu kami bagaimana ia akan memanggil sebuah perintah).Banyak kasus yang sudut kasus, tetapi ingatlah bahwa
which
/type
sering digunakan dalam kasus-kasus sudut (untuk menemukan jawaban untuk perilaku tak terduga seperti: ? Mengapa di bumi adalah bahwa perintah berperilaku seperti itu, mana yang saya menelepon ).Sebagian besar sistem, sebagian besar shell mirip Bourne: fungsi
Kasus yang paling jelas adalah untuk fungsi:
Alasannya adalah bahwa
which
hanya melaporkan tentang executable, dan kadang-kadang tentang alias (meskipun tidak selalu yang dari shell Anda ), bukan fungsi.GNU yang man page memiliki contoh yang rusak (karena mereka lupa kutip
$@
) tentang bagaimana menggunakannya untuk melaporkan fungsi juga, tetapi seperti halnya untuk alias, karena ia tidak mengimplementasikan parser sintaksis shell, itu mudah dibodohi:Sebagian besar sistem, sebagian besar cangkang mirip Bourne: builtin
Kasus lain yang jelas adalah builtin atau kata kunci, karena
which
menjadi perintah eksternal tidak memiliki cara untuk mengetahui builtin apa yang dimiliki shell Anda (dan beberapa shell sukazsh
,bash
atauksh
dapat memuat builtin secara dinamis):(itu tidak berlaku untuk di
zsh
manawhich
builtin)Solaris 10, AIX 7.1, HP / UX 11i, Tru64 5.1 dan banyak lainnya:
Itu karena pada sebagian besar Unices komersial,
which
(seperti dalam implementasi asli pada 3BSD) adalahcsh
skrip yang berbunyi~/.cshrc
. Alias yang akan dilaporkan adalah yang didefinisikan di sana terlepas dari alias yang saat ini telah Anda tentukan dan terlepas dari shell yang sebenarnya Anda gunakan.Di HP / UX atau Tru64:
(versi Solaris dan AIX telah memperbaiki masalah itu dengan menyimpan
$path
sebelum membaca~/.cshrc
dan memulihkannya sebelum mencari perintah)Atau:
(tentu saja, menjadi
csh
skrip yang tidak dapat Anda harapkan berfungsi dengan argumen yang berisi spasi ...)CentOS 6.4, bash
Di sistem itu, ada alias yang didefinisikan di seluruh sistem yang membungkus
which
perintah GNU .Output palsu karena
which
membaca output daribash
'salias
tetapi tidak tahu bagaimana untuk mengurai dengan benar dan menggunakan heuristik (satu alias per baris, terlihat untuk pertama ditemukan perintah setelah|
,;
,&
...)Hal terburuk pada CentOS adalah
zsh
memilikiwhich
perintah built - in yang sangat baik tetapi CentOS berhasil memecahkannya dengan menggantinya dengan alias tidak berfungsi untuk GNUwhich
.Debian 7.0, ksh93:
(meskipun berlaku untuk kebanyakan sistem dengan banyak cangkang)
Di Debian,
/bin/which
adalah/bin/sh
skrip. Dalam kasus saya,sh
menjadidash
tetapi sama sajabash
.Unset
PATH
bukan untuk menonaktifkanPATH
pencarian, tetapi berarti menggunakan PATH default sistem yang sayangnya pada Debian, tidak ada yang setuju (dash
danbash
memiliki/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
,zsh
memiliki/bin:/usr/bin:/usr/ucb:/usr/local/bin
,ksh93
memiliki/bin:/usr/bin
,mksh
memiliki/usr/bin:/bin
($(getconf PATH)
),execvp()
(seperti dienv
) telah:/bin:/usr/bin
(ya, mencari di direktori saat ini terlebih dahulu! )).Itulah sebabnya
which
mendapatkan salah di atas karena itu menggunakandash
'standar sPATH
yang berbeda dariksh93
' sTidak lebih baik dengan GNU
which
yang melaporkan:(Menariknya, memang ada
/usr/local/bin/which
pada sistem saya yang sebenarnya merupakanakanga
skrip yang datang denganakanga
(rc
turunan shell di mana defaultnyaPATH
adalah/usr/ucb:/usr/bin:/bin:.
))bash, sistem apa pun:
Yang dimaksud Chris dalam jawabannya :
Juga setelah menelepon
hash
secara manual:Sekarang kasus di mana
which
dan kadangtype
gagal:Sekarang, dengan beberapa cangkang:
Dengan yang lain:
Baik
which
atautype
bisa tahu sebelumnya bahwab/foo
tidak dapat dijalankan. Beberapa kerang sepertibash
,ksh
atauyash
, saat menjalankanfoo
memang akan mencoba untuk menjalankanb/foo
dan melaporkan kesalahan, sementara yang lain (sepertizsh
,ash
,csh
,Bourne
,tcsh
) akan menjalankana/foo
pada kegagalanexecve()
sistem panggilanb/foo
.sumber
mksh
sebenarnya menggunakan sesuatu yang berbeda untuk default$PATH
: pertama, konstanta waktu kompilasi sistem operasi_PATH_DEFPATH
digunakan (paling umum pada BSD), kemudian,confstr(_CS_PATH, …)
digunakan (POSIX), dan jika keduanya tidak ada atau gagal,/bin:/usr/bin:/sbin:/usr/sbin
digunakan.ls
merupakan fungsi yang digunakannyals
dari PATH. Danwhich
boleh mengatakan kepada Anda yang mana yang digunakan/usr/bin/ls
atau/usr/local/bin/ls
. Saya tidak melihat "Mengapa tidak menggunakan yang" ....which ls
akan memberi saya/bin/ls
terlepas dari apakahls
fungsi panggilan/bin/ls
atau/opt/gnu/bin/ls
ataudir
atau tidak sama sekali. TKI,which
(yang implementasi, IMMV) memberikan sesuatu yang tidak relevanls
fungsi saya adalah. Saya tahu bahwa sayals
fungsi memanggills
dariPATH
. Sekarangwhich
beri tahu saya di mana file itu. Anda hanya melihat satu kasus penggunaan tunggal: "Apa yang akan dilakukan shell saya dengan perintah ini." Untuk kasus penggunaanwhich
ini salah, benar. Tetapi ada kasus penggunaan lain di mana (GNU)which
adalah hal yang tepat.which
implementasinya. Beberapa akan memberi tahu Anda itu adalah alias (jika Anda memiliki alias yang dikonfigurasi, atau jika ada~/.cshrc
di rumah Anda yang memiliki alias seperti itu), beberapa akan memberi Anda jalur tetapi yang salah dalam beberapa kondisi.sh -c 'command -v ls'
, meskipun tidak sempurna masih lebih mungkin untuk memberikan jawaban yang tepat untuk persyaratan yang berbeda (dan juga standar).Satu hal yang (dari skim cepat saya) tampaknya Stephane tidak menyebutkan adalah bahwa
which
tidak tahu tentang tabel hash path shell Anda. Ini memiliki efek yang mungkin mengembalikan hasil yang tidak mewakili apa yang sebenarnya dijalankan, yang membuatnya tidak efektif dalam debugging.sumber
Dalam semangat UNIX: Buat setiap program melakukan satu hal dengan baik.
Jika tujuannya adalah untuk menjawab: Yang dieksekusi ada dengan ini nama?
Program yang dapat dieksekusi yang disediakan dengan sistem Debian adalah jawaban yang bagus. Yang disediakan dengan csh termasuk alias, yang merupakan sumber masalah. Yang disediakan oleh beberapa shell sebagai internal builtin memiliki tujuan yang berbeda. Baik gunakan yang dapat dieksekusi atau gunakan skrip yang disediakan di akhir jawaban ini.
Jika skrip ini digunakan, apa jawabannya bersih, sederhana dan bermanfaat.
Sasaran ini akan cocok dengan kalimat pertama dari pertanyaan Anda:
Jika Anda memiliki sistem yang tidak memiliki executable yang disebut (sebagian besar sistem linux memilikinya), Anda dapat membuatnya
~/bin/which
sebelumnya/bin/
di PATH sehingga sistem yang dapat dieksekusi pribadi menimpa yang seperti di bagian bawah posting ini:Eksekusi itu akan mencantumkan (secara default) semua executable yang ditemukan di PATH. Jika hanya yang pertama diperlukan, opsi
-f
tersedia.Pada titik ini kita jatuh ke tujuan yang berbeda:
apa yang akan dieksekusi shell (setelah penguraian)
Itu berasal dari kalimat kedua Anda:
Subjek kedua ini berusaha menemukan jawaban yang baik untuk pertanyaan yang agak sulit dijawab. Kerang memiliki pandangan yang berbeda, kasus sudut dan (minimal) interpretasi yang berbeda. Menambah itu:
Dan tentu saja, semua upaya cocok dengan tujuan itu.
Hindari yang mana?
Saya bertanya-tanya: Mengapa harus dikatakan jika
which
berfungsi dengan baik (setidaknya dalam bahasa debian)?Dalam semangat UNIX: Buat setiap program melakukan satu hal dengan baik.
The eksternal Program
which
melakukan satu hal: Cari dieksekusi pertama di PATH yang memiliki nama yang sama dengan nama perintah . Dan melakukannya dengan cukup baik.Saya tidak tahu ada program atau utilitas lain yang menjawab pertanyaan ini dengan cara yang lebih mendasar. Dengan demikian, ini berguna dan dapat digunakan saat dibutuhkan.
Alternatif terdekat tampaknya adalah
command -pv commandName
:, tetapi itu juga akan melaporkan tentang builtin dan alias. Bukan jawaban yang sama.Tentu saja
which
terbatas, tidak menjawab semua pertanyaan, tidak ada alat yang bisa melakukan itu (yah, belum ...). Tetapi berguna ketika digunakan untuk menjawab pertanyaan yang dirancang untuk dijawab (yang tepat di atas). Banyak sukaed
terbatas dan kemudiansed
muncul (atauvi
/vim
). Atau sukaawk
terbatas dan membuat Perl muncul dan meluas. Namun,ed
,sed
atau / danawk
memiliki kasus penggunaan tertentu di manavim
atauperl
yang tidak alat terbaik.Mungkin karena
which
menjawab hanya sebagian dari pertanyaan yang mungkin ditanyakan pengguna shell:Apa yang sedang dieksekusi ketika saya mengetik commandName?
Eksternal yang mana
Yang harus tersedia (dalam banyak sistem) sebagai executable eksternal.
Satu-satunya cara pasti untuk memanggil alat eksternal itu adalah menggunakan env untuk keluar dari shell dan kemudian memanggil
which
(yang bekerja di semua shell):Atau gunakan path lengkap ke
which
(yang dapat bervariasi pada sistem yang berbeda):Mengapa itu
hack
dibutuhkan? Karena beberapa kerang (khususnya zsh) bersembunyiwhich
:Menjadi alat eksternal (seperti
env
) dengan sempurna menjelaskan mengapa itu tidak akan melaporkan informasi internal shell. Seperti alias, fungsi, bawaan, variabel bawaan, variabel shell (tidak diekspor), dll:Output kosong
ll
(alias umum untukll='ls -l'
) menunjukkan bahwall
tidak terkait dengan program yang dapat dieksekusi, atau setidaknya, bahwa tidak ada file yang dapat dieksekusi yang disebutkanll
dalam PATH. Penggunaanll
harus memanggil sesuatu yang lain, dalam hal ini, alias:type
dancommand
Perintah
type
dancommand -v
diminta oleh POSIX. Mereka seharusnya diharapkan bekerja di sebagian besar cangkang, dan mereka melakukannya, kecuali dalam csh, tcsh, fish dan rc.Kedua perintah dapat digunakan untuk memberikan sudut pandang lain yang perintahnya akan dieksekusi.
whence
,where
,whereis
,whatis
,hash
Lalu, ada
whence
,where
,whereis
,whatis
,hash
, dan beberapa orang lain. Semua jawaban berbeda untuk pertanyaan serupa. Semua bekerja dengan cara yang berbeda dalam cangkang yang berbeda. Mungkin,whence
adalah yang paling umum setelahnyatype
. Yang lain adalah solusi khusus yang menjawab pertanyaan yang sama dengan cara yang berbeda.Mungkin
which
pertama yang tahu jika ada yang dapat dieksekusi dengan nama CommandName , kemudiantype
dancommand
kemudian, jika CommandName belum ditemukan belum:whence
,where
,whereis
,whatis
,hash
dalam urutan itu.Script Shell untuk menyediakan yang
which
dapat dieksekusi.sumber
Saya belum pernah mendengarnya. Harap berikan contoh spesifik. Saya akan khawatir tentang distribusi linux Anda dan paket perangkat lunak yang diinstal, dari mana
which
asalnya!SLES 11,4 x86-64
dalam versi tcsh 6.18.01:
dalam versi bash 3.2-147:
which
adalah bagian dari util-linux paket standar yang didistribusikan oleh Organisasi Kernel Linux untuk digunakan sebagai bagian dari sistem operasi Linux. Ini juga menyediakan file-file lain inisaya
util-linux
adalah versi 2.19. Catatan rilis dapat dengan mudah ditemukan kembali ke tanggal v2.13 (28-Agustus-2007). Tidak yakin apa maksud atau tujuan dari hal ini, itu pasti tidak dijawab dalam hal panjang yang dibatalkan 331 kali.sumber
which -v
tunjukkan, itulah GNU yang (yang boros disebutkan dalam jawaban lain dan sama sekali tidak spesifik untuk Linux), bukan util-linux yang AFAIK tidak pernah menyertakanwhich
utilitas. util-linux 2.19 berasal dari 2011, GNU yang 2.19 berasal dari 2008.