Bash Alias ​​- Precedence / Shadowing (/ hiding / failing)

Aug 17 2020

Ho alcuni alias impostati (in questo ordine) in .bashrc:

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

Confermandoli con aliasdopo l'approvvigionamento:

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

Posso eseguire il nuovo alias lsbene, e si concatena all'alias lsc, quindi esegue il comando associato all'alias lsc. Posso anche correre lscRe funziona come previsto.

Se provo a eseguire lscse stesso, però, ottengo:

$ lsc
lsc: command not found

Qualche idea del motivo per cui la shell sembra nascondere / nascondere l'alias lsc in questo scenario? (Mi rendo conto che è inutile eseguire "lsc" quando posso semplicemente eseguire "ls" per ottenere lo stesso risultato qui, ma sto cercando di capire il comportamento delle shell in questo scenario).

EDIT: soluzioni alternative di seguito per il comportamento della shell (bash) fornito nelle risposte alle domande.

Alcune risposte veramente utili sono state fornite alla domanda originale. Al fine di cortocircuitare il comportamento di espansione spiegato nelle risposte, sembrano esserci almeno due modi per impedire a un secondo alias, di tentare di espandere un comando che hai già alias. Ad esempio, se hai alias cmd='cmd --stuff'che sovrascrive un comando nativo chiamato cmd, puoi impedire che l'alias 'cmd' venga utilizzato al posto del nativo cmdall'interno di altri alias, tramite:

(grazie al commento di wjandrea per questo primo approccio)

  1. prefisso cmdcon 'comando' nell'altro alias esalias other-cmd-alias='command cmd --other-stuff'

o,

  1. Allo stesso modo, puoi sfuggire agli alias (come puoi anche fare sulla riga di comando), all'interno di altri alias anteponendo un backslash '', ad es alias other-cmd-alias='\cmd --other-stuff'.

Risposte

13 John1024 Aug 17 2020 at 11:58

Bash consente agli alias di contenere alias, ma ha protezioni integrate contro i loop infiniti. Nel tuo caso, quando digiti lsc, bash espande prima l'alias in:

ls -Flatr --color=always

Poiché lsè anche un alias, bash lo espande in:

lsc -Flatr --color=always

lscè un alias ma, abbastanza sensatamente, bash si rifiuta di espanderlo una seconda volta . Se ci fosse un programma chiamato lsc, bash lo eseguirà. Ma non c'è ed è per questo che ottieni command not found.

Addendum

È diverso quando lscRviene eseguito. lscRsi espande a:

ls -FlatrR --color=always

Poiché lsè un alias, si espande in:

lsc -FlatrR --color=always

Poiché lscè un alias, si espande in:

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

Poiché lsè già stato espanso una volta, bash si rifiuta di espanderlo una seconda volta . Poiché lsesiste un vero comando chiamato , viene eseguito.

Storia

Come notato da Schily nei commenti, bash ha preso in prestito il concetto di non espandere un alias una seconda volta da ksh .

A parte

Gli alias sono utili ma non molto potenti. Se sei tentato di fare qualcosa di complesso con un alias, come la sostituzione di un argomento, non farlo; usa invece una funzione di shell.

6 muru Aug 17 2020 at 12:00

Dal manuale di bash :

La prima parola del testo sostitutivo viene verificata per gli alias, ma una parola identica a un alias che viene espanso non viene espansa una seconda volta. Ciò significa che è possibile creare un alias lscon " ls -F", ad esempio, e Bash non tenta di espandere ricorsivamente il testo sostitutivo.

Nel lsalias, lsviene espansa per lscpoi nuovamente ls -Flatr --color=always, e si ferma l'espansione alias, poiché lsoriginariamente in fase di espansione. Quindi, il comando viene eseguito correttamente, lsora viene risolto in un comando esterno.

Nel lscalias, lscviene espanso a ls -Flatr --color=always, e quindi lsè ora esteso per lsce le fermate espansione alias, poiché lscoriginariamente in fase di espansione. Quindi, il comando fallisce, dal momento che bash non ne conosce altri lsc.