Bash Alias - Precedência / Sombreamento (/ hide / failing)
Tenho alguns aliases configurados (nesta ordem) em .bashrc:
alias ls="lsc"
alias lsc='ls -Flatr --color=always'
alias lscR='ls -FlatrR --color=always'
Confirmando-os com alias
após o fornecimento:
alias ls='lsc'
alias lsc='ls -Flatr --color=always'
alias lscR='ls -FlatrR --color=always'
Posso executar o novo alias ls
perfeitamente e ele se encadeia com o alias lsc e, em seguida, executa o comando associado ao alias lsc. Também posso correr lscR
e funciona como esperado.
lsc
Porém, se eu tentar funcionar sozinho, obtenho:
$ lsc
lsc: command not found
Alguma ideia de por que o shell parece estar ocultando / ocultando o alias lsc neste cenário? (Eu percebo que é inútil executar 'lsc' quando posso apenas executar 'ls' para obter o mesmo resultado aqui, mas estou tentando entender o comportamento dos shells neste cenário).
EDIT: Soluções alternativas abaixo para o comportamento do shell (bash) fornecido nas respostas às perguntas.
Algumas respostas realmente úteis foram fornecidas à pergunta original. Para causar um curto-circuito no comportamento de expansão explicado nas respostas, parece haver pelo menos duas maneiras de impedir um segundo alias, de tentar expandir um comando que você já alterou. Por exemplo, se você tem o alias cmd='cmd --stuff'
que está substituindo um comando nativo chamado cmd
, pode evitar que o alias 'cmd' seja usado no lugar do nativo cmd
em outros aliases:
(graças ao comentário de wjandrea por esta primeira abordagem)
- prefixando
cmd
com 'command' no outro alias, por exemploalias other-cmd-alias='command cmd --other-stuff'
ou,
- Da mesma forma, você pode escapar dos aliases (como também pode fazer na linha de comando), dentro de outros aliases prefixando com uma barra invertida '', por exemplo
alias other-cmd-alias='\cmd --other-stuff'
.
Respostas
O Bash permite que apelidos contenham apelidos, mas tem proteções integradas contra loops infinitos. No seu caso, quando você digita lsc
, bash primeiro expande o alias para:
ls -Flatr --color=always
Como ls
também é um alias, o bash o expande para:
lsc -Flatr --color=always
lsc
é um alias, mas, sensatamente, bash se recusa a expandi-lo uma segunda vez . Se houvesse um programa chamado lsc
, o bash o executaria. Mas, não existe e é por isso que você consegue command not found
.
Termo aditivo
É diferente quando lscR
é executado. lscR
expande para:
ls -FlatrR --color=always
Como ls
é um alias, ele se expande para:
lsc -FlatrR --color=always
Como lsc
é um alias, ele se expande para:
ls -Flatr --color=always -FlatrR --color=always
Como ls
já foi expandido uma vez, o bash se recusa a expandi-lo uma segunda vez . Como ls
existe um comando real chamado , ele é executado.
História
Conforme observado por Schily nos comentários, o bash pegou emprestado o conceito de não expandir um alias uma segunda vez do ksh .
a parte, de lado
Os aliases são úteis, mas não muito poderosos. Se você se sentir tentado a fazer algo complexo com um apelido, como substituição de argumento, não faça; use uma função shell em vez disso.
Do manual do bash :
A primeira palavra do texto de substituição é testada para aliases, mas uma palavra idêntica a um alias sendo expandido não é expandida uma segunda vez. Isso significa que pode-se
ls
criar um atalho para "ls -F
", por exemplo, e o Bash não tenta expandir recursivamente o texto de substituição.
No ls
alias, ls
é expandido para lsc
e novamente para ls -Flatr --color=always
, e aí a expansão do alias é interrompida, pois ls
estava sendo originalmente expandido. Assim, o comando funciona bem, ls
agora sendo resolvido para um comando externo.
No lsc
alias, lsc
é expandido para ls -Flatr --color=always
e, em seguida, ls
agora é expandido para lsc
e aí a expansão do alias é interrompida, pois lsc
estava sendo originalmente expandido. Portanto, o comando falha, pois o bash não conhece nenhum outro lsc
.