Bash Alias - Precedence / Shadowing (/ hiding / failing)
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 alias
dopo l'approvvigionamento:
alias ls='lsc'
alias lsc='ls -Flatr --color=always'
alias lscR='ls -FlatrR --color=always'
Posso eseguire il nuovo alias ls
bene, e si concatena all'alias lsc, quindi esegue il comando associato all'alias lsc. Posso anche correre lscR
e funziona come previsto.
Se provo a eseguire lsc
se 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 cmd
all'interno di altri alias, tramite:
(grazie al commento di wjandrea per questo primo approccio)
- prefisso
cmd
con 'comando' nell'altro alias esalias other-cmd-alias='command cmd --other-stuff'
o,
- 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
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 lscR
viene eseguito. lscR
si 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é ls
esiste 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.
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
ls
con "ls -F
", ad esempio, e Bash non tenta di espandere ricorsivamente il testo sostitutivo.
Nel ls
alias, ls
viene espansa per lsc
poi nuovamente ls -Flatr --color=always
, e si ferma l'espansione alias, poiché ls
originariamente in fase di espansione. Quindi, il comando viene eseguito correttamente, ls
ora viene risolto in un comando esterno.
Nel lsc
alias, lsc
viene espanso a ls -Flatr --color=always
, e quindi ls
è ora esteso per lsc
e lì le fermate espansione alias, poiché lsc
originariamente in fase di espansione. Quindi, il comando fallisce, dal momento che bash non ne conosce altri lsc
.