Alias ​​bash - Priorité / Ombrage (/ masquage / échec)

Aug 17 2020

J'ai quelques alias configurés (dans cet ordre) dans .bashrc:

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

Les confirmer avec aliasaprès sourcing:

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

Je peux très bien exécuter le nouvel aliasé ls, et il se connecte à l'alias lsc, puis exécute la commande associée à l'alias lsc. Je peux aussi courir lscRet cela fonctionne comme prévu.

Si j'essaye de fonctionner tout lscseul, j'obtiens:

$ lsc
lsc: command not found

Une idée de la raison pour laquelle le shell semble masquer / masquer l'alias lsc dans ce scénario? (Je me rends compte qu'il est inutile d'exécuter 'lsc' alors que je peux simplement exécuter 'ls' pour obtenir le même résultat ici, mais j'essaie de comprendre le comportement des shells dans ce scénario).

EDIT: solutions de contournement ci-dessous pour le comportement du shell (bash) fourni dans les réponses aux questions.

Des réponses vraiment utiles ont été apportées à la question initiale. Afin de court-circuiter le comportement d'expansion qui est expliqué dans les réponses, il semble y avoir au moins deux façons d'empêcher un deuxième alias d'essayer d'étendre une commande que vous avez déjà aliasée. Par exemple, si vous avez alias cmd='cmd --stuff'qui remplace une commande native appelée cmd, vous pouvez empêcher que l'alias 'cmd' ne soit utilisé à la place du natif cmddans d'autres alias, en:

(merci au commentaire de wjandrea pour cette première approche)

  1. préfixer cmdavec 'commande' dans l'autre alias, par exemplealias other-cmd-alias='command cmd --other-stuff'

ou,

  1. De même, vous pouvez échapper les alias (comme vous pouvez également le faire sur la ligne de commande), dans d'autres alias en préfixant avec une barre oblique inverse '', par exemple alias other-cmd-alias='\cmd --other-stuff'.

Réponses

13 John1024 Aug 17 2020 at 11:58

Bash permet aux alias de contenir des alias, mais il dispose de protections intégrées contre les boucles infinies. Dans votre cas, lorsque vous tapez lsc, bash développe d'abord l'alias en:

ls -Flatr --color=always

Puisqu'il lss'agit également d'un alias, bash l'étend à:

lsc -Flatr --color=always

lscest un alias mais, de manière tout à fait raisonnable, bash refuse de l'étendre une seconde fois . S'il y avait un programme nommé lsc, bash l'exécuterait. Mais, il n'y en a pas et c'est pourquoi vous obtenez command not found.

Addenda

C'est différent quand lscRs'exécute. lscRs'étend à:

ls -FlatrR --color=always

Puisqu'il lss'agit d'un alias, cela s'étend à:

lsc -FlatrR --color=always

Puisqu'il lscs'agit d'un alias, cela s'étend à:

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

Puisqu'il lsa déjà été étendu une fois, bash refuse de l'étendre une seconde fois . Puisqu'une vraie commande appelée lsexiste, elle est exécutée.

L'histoire

Comme l'a noté Schily dans les commentaires, bash a emprunté le concept de ne pas développer un alias une deuxième fois à ksh .

De côté

Les alias sont utiles mais pas très puissants. Si vous êtes tenté de faire quelque chose de complexe avec un alias, comme la substitution d'argument, ne le faites pas; utilisez plutôt une fonction shell.

6 muru Aug 17 2020 at 12:00

À partir du manuel bash :

Le premier mot du texte de remplacement est testé pour les alias, mais un mot identique à un alias en cours de développement n'est pas développé une deuxième fois. Cela signifie que l'on peut utiliser un alias lssur " ls -F", par exemple, et Bash n'essaye pas de développer récursivement le texte de remplacement.

Dans l' lsalias, lsest développé vers lsc, puis de nouveau vers ls -Flatr --color=always, et là, l'expansion de l'alias s'arrête, car elle lsétait initialement développée. Ainsi, la commande fonctionne correctement, lsétant maintenant résolue en une commande externe.

Dans l' lscalias, lscest étendu à ls -Flatr --color=always, puis lsest maintenant développé vers lscet là, l'expansion de l'alias s'arrête, car elle lscétait initialement développée. Donc, la commande échoue, car bash n'en connaît pas d'autre lsc.