Bash Alias - Precedencia / Sombreado (/ ocultando / fallando)
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 alias
despué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 lscR
y funciona como se esperaba.
Sin embargo, si trato de ejecutarlo lsc
solo, 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 cmd
dentro de otros alias, mediante:
(gracias al comentario de wjandrea por este primer enfoque)
- prefijado
cmd
con 'comando' en el otro alias, por ejemploalias other-cmd-alias='command cmd --other-stuff'
o,
- 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
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 ls
que también es un alias, bash lo expande a:
lsc -Flatr --color=always
lsc
es 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 lscR
corre. lscR
se expande a:
ls -FlatrR --color=always
Dado que ls
es un alias, esto se expande a:
lsc -FlatrR --color=always
Dado que lsc
es un alias, esto se expande a:
ls -Flatr --color=always -FlatrR --color=always
Dado que ls
ya se expandió una vez, bash se niega a expandirlo por segunda vez . Dado que ls
existe 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.
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
ls
a "ls -F
", por ejemplo, y Bash no intenta expandir recursivamente el texto de reemplazo.
En el ls
alias, ls
se expande ay lsc
luego nuevamente a ls -Flatr --color=always
, y allí se detiene la expansión del alias, ya que ls
originalmente se estaba expandiendo. Entonces, el comando funciona bien, ls
ahora se resuelve en un comando externo.
En el lsc
alias, lsc
se expande a ls -Flatr --color=always
, y luego ls
ahora se expande lsc
y allí se detiene la expansión de alias, ya que lsc
originalmente se estaba expandiendo. Entonces, el comando falla, ya que bash no conoce ningún otro lsc
.