Bash Alias ​​- Precedencia / Sombreado (/ ocultando / fallando)

Aug 17 2020

Tengo algunos alias configurados (en este orden) en .bashrc:

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

Confirmándolos con aliasdespués del abastecimiento:

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

Puedo ejecutar el nuevo alias sin problemas ls, y se encadena al alias lsc, y luego ejecuta el comando asociado con el alias lsc. También puedo correr lscRy funciona como se esperaba.

Sin embargo, si trato de ejecutarlo lscsolo, obtengo:

$ lsc
lsc: command not found

¿Alguna idea de por qué el shell parece estar ocultando / ocultando el alias lsc en este escenario? (Me doy cuenta de que no tiene sentido ejecutar 'lsc' cuando puedo ejecutar 'ls' para obtener el mismo resultado aquí, pero estoy tratando de comprender el comportamiento de los shells en este escenario).

EDITAR: Soluciones alternativas a continuación para el comportamiento del shell (bash) proporcionado en las respuestas a las preguntas.

Se han proporcionado algunas respuestas realmente útiles a la pregunta original. Para cortocircuitar el comportamiento de expansión que se explica en las respuestas, parece haber al menos dos formas de evitar que un segundo alias intente expandir un comando al que ya ha asignado un alias. Por ejemplo, si tiene alias cmd='cmd --stuff'que anular un comando nativo llamado cmd, puede evitar que el alias 'cmd' se use en lugar del nativo cmddentro de otros alias, mediante:

(gracias al comentario de wjandrea por este primer enfoque)

  1. prefijado cmdcon 'comando' en el otro alias, por ejemploalias other-cmd-alias='command cmd --other-stuff'

o,

  1. De manera similar, puede escapar de los alias (como también puede hacer en la línea de comando), dentro de otros alias prefijando una barra invertida '', por ejemplo alias other-cmd-alias='\cmd --other-stuff'.

Respuestas

13 John1024 Aug 17 2020 at 11:58

Bash permite que los alias contengan alias, pero tiene protecciones integradas contra bucles infinitos. En su caso, cuando escribe lsc, bash primero expande el alias a:

ls -Flatr --color=always

Dado lsque también es un alias, bash lo expande a:

lsc -Flatr --color=always

lsces un alias pero, con bastante sensatez, bash se niega a expandirlo por segunda vez . Si hubiera un programa llamado lsc, bash lo ejecutaría. Pero, no lo hay y es por eso que lo consigues command not found.

Apéndice

Es diferente cuando lscRcorre. lscRse expande a:

ls -FlatrR --color=always

Dado que lses un alias, esto se expande a:

lsc -FlatrR --color=always

Dado que lsces un alias, esto se expande a:

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

Dado que lsya se expandió una vez, bash se niega a expandirlo por segunda vez . Dado que lsexiste un comando real llamado , se ejecuta.

Historia

Como señaló Schily en los comentarios, bash tomó prestado el concepto de no expandir un alias por segunda vez de ksh .

Aparte

Los alias son útiles pero no muy poderosos. Si tiene la tentación de hacer algo complejo con un alias, como la sustitución de argumentos, no lo haga; use una función de shell en su lugar.

6 muru Aug 17 2020 at 12:00

Desde el manual de bash :

La primera palabra del texto de reemplazo se prueba para buscar alias, pero una palabra que es idéntica a un alias que se está expandiendo no se expande por segunda vez. Esto significa que uno puede alias lsa " ls -F", por ejemplo, y Bash no intenta expandir recursivamente el texto de reemplazo.

En el lsalias, lsse expande ay lscluego nuevamente a ls -Flatr --color=always, y allí se detiene la expansión del alias, ya que lsoriginalmente se estaba expandiendo. Entonces, el comando funciona bien, lsahora se resuelve en un comando externo.

En el lscalias, lscse expande a ls -Flatr --color=always, y luego lsahora se expande lscy allí se detiene la expansión de alias, ya que lscoriginalmente se estaba expandiendo. Entonces, el comando falla, ya que bash no conoce ningún otro lsc.