Urutan executable dimulai di bash

14

Jika saya menjalankan testperintah dalam bash, test(mengevaluasi ekspresi kondisional) utilitas bawaan dimulai:

$ type test
test is a shell builtin
$ type -a test
test is a shell builtin
test is /usr/local/bin/test
test is /usr/bin/test
$ 

Namun, seperti yang terlihat pada output di type -a testatas, ada testdirektori lain di / usr / local / bin dan satu lagi di direktori / usr / bin. Bagaimana perintah yang dapat dieksekusi, yaitu apakah perintah bawaan selalu lebih disukai dan kemudian perintah lainnya bergantung pada urutan direktori dalam variabel $ PATH? Selain itu, apakah mungkin untuk mengubah urutan executable yang dimulai, mis. Jika saya mengetik test, maka / usr / bin / test dimulai bukannya bash-builtin test?

Martin
sumber
Anda dapat menentukan path lengkap saat memanggil perintah, mis., /usr/bin/test -f "$file"...
jasonwryan
@jasonwryan Saya mengetahui hal ini, tapi saya hanya tertarik jika ada cara untuk mengubah urutan executable yang dimulai.
Martin

Jawaban:

25

Prioritas tertinggi adalah alias bash, lalu builtin khusus (hanya dalam mode POSIX), lalu berfungsi, lalu builtin, lalu pencarian masuk $PATH.

Untuk menjalankan builtin, gunakan builtin test.
Untuk menjalankan aplikasi eksternal, menggunakan path eksplisit: /bin/test.
Untuk mengabaikan fungsi dan alias, gunakan command test.
Untuk mem-bypass alias saja, gunakan \testatau jenis ekspansi lainnya.

Dimungkinkan untuk menonaktifkan / mengaktifkan builtin dengan enable test.

(Diperbarui menurut komentar di bawah)
(Memperbaiki edit admin yang salah yang dibangun oleh bash disable- pada kenyataannya, hanya ada enable)

gena2x
sumber
1
@ 1_CR gena2x benar. Jawaban saya menghilangkan builtin khusus, yang diutamakan daripada fungsi sesuai POSIX (meskipun beberapa shell tidak sesuai; bash hanya sesuai dalam mode POSIX).
Gilles 'SANGAT berhenti menjadi jahat'
1
Suntingan yang disarankan: Alias ​​dinonaktifkan ketika Anda mengutip perintah (atau bagiannya), seperti pada \testatau 'test'atau tes't'.
John Kugelman
2
Itu bukan gambaran lengkap. Tampaknya segala jenis ekspansi (dalam manual bash, semua substitusi, ekspansi tilde dan sebagainya yang disebut ekspansi ) menonaktifkan alias. Saya mencoba.
gena2x
1
Kutipan dari halaman pesta man:.. "Kata pertama dari setiap perintah sederhana, jika kuotasi, diperiksa untuk melihat apakah ia memiliki alias Jika demikian, kata yang diganti dengan teks alias Karakter /, $, backtick, dan =dan salah satu karakter meta shell atau mengutip karakter yang tercantum di atas mungkin tidak muncul dalam nama alias. "
John Kugelman
2
+1 untuk petunjuk dalam membantu saya menemukan sumber informasi ini: ada di halaman bash man, di bawah bagian COMMAND EXECUTION, paragraf kedua dan ketiga.
twan163
6

Perintah bawaan selalu lebih disukai daripada perintah eksternal. Rasionalnya adalah bahwa perintah bawaan lebih cepat (dan dalam beberapa kasus, seperti cdatau , hanya perintah bawaan yang dapat memiliki efek yang diinginkan).test -o BASH_OPTION

Terkadang perintah eksternal mungkin memiliki kapabilitas yang tidak dimiliki shell builtin. Dalam hal ini, Anda dapat memanggil perintah eksternal dengan memberikan jalur eksplisit (yaitu berisi garis miring) (ini memintas kekhawatiran tentang urutan masuk $PATH). Jika Anda tidak ingin melakukan hard-code pada jalur eksternal tetapi Anda ingin mencegah penggunaan builtin, Anda dapat menggunakan "$(type -P test)"(modal catatan P) dalam bash, "$(whence -p test)"di ksh, dan =testdi zsh. Cara lain untuk memaksa penggunaan perintah eksternal adalah dengan menggunakan commandbuiltin ( command -p test …) atau melalui envutilitas ( env test …).

Di zsh, Anda dapat menonaktifkan bawaan dengan disable test. Ini permanen (untuk shell atau subkulit saat ini) sampai builtin diaktifkan kembali dengan enable test. Dalam bash, Anda dapat melakukan hal yang sama enable -n testuntuk menonaktifkan dan enable testmengaktifkan kembali.

Anda dapat menggunakan alias atau fungsi untuk memaksa pelaksanaan perintah yang berbeda, misalnya alias test=/usr/bin/testatau test () { /usr/bin/test "$@"; }. Jika Anda memiliki alias seperti itu, Anda dapat mencegah penggunaannya dengan mengutip bagian mana pun darinya, mis. \testAkan melakukan fungsi normal / builtin / pencarian eksternal. Perhatikan bahwa tergantung pada shell dan pengaturannya, definisi alias dalam suatu fungsi dapat diperluas ketika suatu fungsi dibaca atau ketika dijalankan. Jika Anda telah mendefinisikan suatu fungsi, Anda dapat menggunakan command testuntuk mencegah pencarian fungsi serta pencarian alias (jadi di sini testbuiltin akan dipanggil kecuali dinonaktifkan).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
tidak envakan cocok di sini juga?
Steven Penny
jadi, jika shell dijalankan dari BusyBox, apakah ada yang lain, biasanya perintah eksternal dari BusyBox yang sama dianggap sebagai internal? misalnya saya menambahkan penuh dfke PATH pada posisi pertama, dihapus alias 'df', which dfmenunjukkan / opt / bin / df, tetapi df berjalan / bin / df -> busybox
papo
@ papo which dftidak selalu menunjukkan kepada Anda apa yang dfberjalan. unix.stackexchange.com/questions/85249/...
Gilles 'SO- stop being evil'