Bash Alias ​​- Precedence / Shadowing (/ menyembunyikan / gagal)

Aug 17 2020

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 aliassetelah mencari:

alias ls='lsc'
alias lsc='ls -Flatr --color=always'
alias lscR='ls -FlatrR --color=always'

Saya dapat menjalankan alias yang lsbaru dengan baik, dan terhubung ke alias lsc, dan kemudian mengeksekusi perintah yang terkait dengan alias lsc. Saya juga bisa menjalankan lscRdan beroperasi seperti yang diharapkan.

Jika saya mencoba menjalankan lscdirinya 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 cmdmengganti perintah asli yang dipanggil , Anda dapat mencegah alias 'cmd' digunakan menggantikan yang asli cmddalam alias lain, dengan:

(terima kasih atas komentar wjandrea untuk pendekatan pertama ini)

  1. mengawali cmddengan 'perintah' di alias lain misalnyaalias other-cmd-alias='command cmd --other-stuff'

atau,

  1. 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

13 John1024 Aug 17 2020 at 11:58

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 lsjuga merupakan alias, bash memperluasnya menjadi:

lsc -Flatr --color=always

lscadalah 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 lscRberlari. lscRberkembang menjadi:

ls -FlatrR --color=always

Karena lsmerupakan alias, ini meluas menjadi:

lsc -FlatrR --color=always

Karena lscmerupakan alias, ini meluas menjadi:

ls -Flatr --color=always -FlatrR --color=always

Karena lssudah diperluas sekali, bash menolak untuk mengembangkannya untuk kedua kalinya . Karena perintah nyata yang disebut lsada, 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.

6 muru Aug 17 2020 at 12:00

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 lsmenjadi " ls -F", misalnya, dan Bash tidak mencoba memperluas teks pengganti secara rekursif.

Dalam lsalias, lsdiperluas ke lscdan kemudian lagi ke ls -Flatr --color=always, dan di sana perluasan alias berhenti, karena lsawalnya diperluas. Jadi, perintahnya berjalan dengan baik, lssekarang diselesaikan menjadi perintah eksternal.

Dalam lscalias, lscdiperluas ke ls -Flatr --color=always, lalu lssekarang diperluas ke lscdan di sana perluasan alias berhenti, karena lscawalnya diperluas. Jadi, perintahnya gagal, karena bash tidak mengetahui yang lain lsc.