Bash Alias - Precedence / Shadowing (/ menyembunyikan / gagal)
Saya memiliki beberapa pengaturan alias (dalam urutan ini) di .bashrc:
alias ls="lsc"
alias lsc='ls -Flatr --color=always'
alias lscR='ls -FlatrR --color=always'
Mengonfirmasi mereka dengan alias
setelah mencari:
alias ls='lsc'
alias lsc='ls -Flatr --color=always'
alias lscR='ls -FlatrR --color=always'
Saya dapat menjalankan alias yang ls
baru dengan baik, dan terhubung ke alias lsc, dan kemudian mengeksekusi perintah yang terkait dengan alias lsc. Saya juga bisa menjalankan lscR
dan beroperasi seperti yang diharapkan.
Jika saya mencoba menjalankan lsc
dirinya sendiri, saya mendapatkan:
$ lsc
lsc: command not found
Adakah ide mengapa shell tampaknya membayangi / menyembunyikan alias lsc dalam skenario ini? (Saya menyadari tidak ada gunanya menjalankan 'lsc' saat saya bisa menjalankan 'ls' untuk mendapatkan hasil yang sama di sini, tetapi saya mencoba memahami perilaku shell dalam skenario ini).
EDIT: Solusi di bawah untuk perilaku shell (bash) yang disediakan dalam jawaban pertanyaan.
Beberapa jawaban yang sangat membantu telah diberikan untuk pertanyaan asli. Untuk memperpendek perilaku ekspansi yang dijelaskan dalam jawaban, tampaknya ada setidaknya dua cara untuk mencegah alias kedua, dari mencoba memperluas perintah yang telah Anda aliasi. Misalnya, jika Anda memiliki alias cmd='cmd --stuff'
yang cmd
mengganti perintah asli yang dipanggil , Anda dapat mencegah alias 'cmd' digunakan menggantikan yang asli cmd
dalam alias lain, dengan:
(terima kasih atas komentar wjandrea untuk pendekatan pertama ini)
- mengawali
cmd
dengan 'perintah' di alias lain misalnyaalias other-cmd-alias='command cmd --other-stuff'
atau,
- Demikian pula, Anda dapat keluar dari alias (seperti yang juga dapat Anda lakukan pada baris perintah), di dalam alias lain dengan mengawali dengan garis miring terbalik '', mis
alias other-cmd-alias='\cmd --other-stuff'
.
Jawaban
Bash mengizinkan alias berisi alias tetapi memiliki perlindungan bawaan terhadap loop tak terbatas. Dalam kasus Anda, saat Anda mengetik lsc
, bash terlebih dahulu memperluas alias menjadi:
ls -Flatr --color=always
Karena ls
juga merupakan alias, bash memperluasnya menjadi:
lsc -Flatr --color=always
lsc
adalah sebuah alias tapi, cukup masuk akal, bash menolak untuk mengembangkannya untuk kedua kalinya . Jika ada program bernama lsc
, bash akan menjalankannya. Tapi, tidak ada dan itulah mengapa Anda mendapatkannya command not found
.
Tambahan
Berbeda saat lscR
berlari. lscR
berkembang menjadi:
ls -FlatrR --color=always
Karena ls
merupakan alias, ini meluas menjadi:
lsc -FlatrR --color=always
Karena lsc
merupakan alias, ini meluas menjadi:
ls -Flatr --color=always -FlatrR --color=always
Karena ls
sudah diperluas sekali, bash menolak untuk mengembangkannya untuk kedua kalinya . Karena perintah nyata yang disebut ls
ada, perintah tersebut dijalankan.
Sejarah
Seperti dicatat oleh Schily di komentar, bash meminjam konsep tidak memperluas alias untuk kedua kalinya dari ksh .
Ke samping
Alias berguna tapi tidak terlalu kuat. Jika Anda tergoda untuk melakukan sesuatu yang kompleks dengan alias, seperti substitusi argumen, jangan; gunakan fungsi shell sebagai gantinya.
Dari manual bash :
Kata pertama dari teks pengganti diuji untuk alias, tetapi kata yang identik dengan alias yang diperluas tidak diperluas untuk kedua kalinya. Ini berarti bahwa seseorang dapat membuat alias
ls
menjadi "ls -F
", misalnya, dan Bash tidak mencoba memperluas teks pengganti secara rekursif.
Dalam ls
alias, ls
diperluas ke lsc
dan kemudian lagi ke ls -Flatr --color=always
, dan di sana perluasan alias berhenti, karena ls
awalnya diperluas. Jadi, perintahnya berjalan dengan baik, ls
sekarang diselesaikan menjadi perintah eksternal.
Dalam lsc
alias, lsc
diperluas ke ls -Flatr --color=always
, lalu ls
sekarang diperluas ke lsc
dan di sana perluasan alias berhenti, karena lsc
awalnya diperluas. Jadi, perintahnya gagal, karena bash tidak mengetahui yang lain lsc
.