Bash Alias ​​- Precedência / Sombreamento (/ hide / failing)

Aug 17 2020

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 aliasapós o fornecimento:

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

Posso executar o novo alias lsperfeitamente e ele se encadeia com o alias lsc e, em seguida, executa o comando associado ao alias lsc. Também posso correr lscRe funciona como esperado.

lscPoré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 cmdem outros aliases:

(graças ao comentário de wjandrea por esta primeira abordagem)

  1. prefixando cmdcom 'command' no outro alias, por exemploalias other-cmd-alias='command cmd --other-stuff'

ou,

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

13 John1024 Aug 17 2020 at 11:58

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 lstambé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. lscRexpande 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 lsjá foi expandido uma vez, o bash se recusa a expandi-lo uma segunda vez . Como lsexiste 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.

6 muru Aug 17 2020 at 12:00

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 lscriar um atalho para " ls -F", por exemplo, e o Bash não tenta expandir recursivamente o texto de substituição.

No lsalias, lsé expandido para lsce novamente para ls -Flatr --color=always, e aí a expansão do alias é interrompida, pois lsestava sendo originalmente expandido. Assim, o comando funciona bem, lsagora sendo resolvido para um comando externo.

No lscalias, lscé expandido para ls -Flatr --color=alwayse, em seguida, lsagora é expandido para lsce a expansão do alias é interrompida, pois lscestava sendo originalmente expandido. Portanto, o comando falha, pois o bash não conhece nenhum outro lsc.