Псевдоним Bash - приоритет / затенение (/ скрытие / сбой)

Aug 17 2020

У меня есть несколько настроек псевдонимов (в этом порядке) в .bashrc:

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

Подтверждение их aliasпосле поиска:

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

Я могу просто запустить новый псевдоним ls, и он будет связан с псевдонимом lsc, а затем выполнит команду, связанную с псевдонимом lsc. Я тоже могу бегать, lscRи все работает как положено.

Если я попытаюсь запустить lscсам себя, то получу:

$ lsc
lsc: command not found

Есть идеи, почему оболочка, кажется, скрывает / скрывает псевдоним lsc в этом сценарии? (Я понимаю, что запускать lsc бессмысленно, если я могу просто запустить ls, чтобы получить тот же результат, но я пытаюсь понять поведение оболочки в этом сценарии).

РЕДАКТИРОВАТЬ: нижеприведенные обходные пути для поведения оболочки (bash), указанные в ответах на вопросы.

На исходный вопрос было дано несколько действительно полезных ответов. Чтобы сократить поведение расширения, которое объясняется в ответах, кажется, есть как минимум два способа предотвратить вторым псевдонимом, пытаясь расширить команду, на которую вы уже указали псевдоним. Например, если у вас есть alias cmd='cmd --stuff'команда cmd, которая переопределяет вызываемую собственную команду , вы можете предотвратить использование псевдонима cmd вместо собственного cmdв других псевдонимах:

(спасибо комментарию wjandrea за этот первый подход)

  1. с префиксом cmd'command' в другом псевдониме, напримерalias other-cmd-alias='command cmd --other-stuff'

или же,

  1. Точно так же вы можете экранировать псевдонимы (как и в командной строке) внутри других псевдонимов, добавив префикс с обратной косой чертой '', например alias other-cmd-alias='\cmd --other-stuff'.

Ответы

13 John1024 Aug 17 2020 at 11:58

Bash действительно позволяет псевдонимам содержать псевдонимы, но имеет встроенную защиту от бесконечных циклов. В вашем случае, когда вы печатаете lsc, bash сначала расширяет псевдоним до:

ls -Flatr --color=always

Поскольку lsэто также псевдоним, bash расширяет его до:

lsc -Flatr --color=always

lscявляется псевдонимом, но, вполне разумно, bash отказывается расширять его во второй раз . Если бы была названа программа lsc, bash запустил бы ее. Но нет, и поэтому вы получаете command not found.

Дополнение

Другое дело, когда lscRбежит. lscRрасширяется до:

ls -FlatrR --color=always

Поскольку lsэто псевдоним, он расширяется до:

lsc -FlatrR --color=always

Поскольку lscэто псевдоним, он расширяется до:

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

Поскольку lsуже был расширен один раз, bash отказывается расширять его второй раз . Поскольку настоящая вызываемая команда lsсуществует, она запускается.

История

Как отметил Шили в комментариях, bash позаимствовал концепцию отказа от расширения псевдонима второй раз у ksh .

В сторону

Псевдонимы полезны, но не очень эффективны. Если вы хотите сделать что-то сложное с псевдонимом, например, подстановку аргументов, не делайте этого; вместо этого используйте функцию оболочки.

6 muru Aug 17 2020 at 12:00

Из руководства bash :

Первое слово замещающего текста проверяется на псевдонимы, но слово, идентичное расширяемому псевдониму, не раскрывается во второй раз. Это означает, что можно использовать псевдоним , например, lsдля " ls -F", и Bash не пытается рекурсивно расширять замещающий текст.

В lsпсевдониме lsрасширяется до, lscа затем снова до ls -Flatr --color=always, и на этом расширение псевдонима останавливается, поскольку lsизначально расширялось. Итак, команда работает нормально, lsтеперь она преобразована во внешнюю команду.

В lscпсевдониме, lscрасширяются до ls -Flatr --color=always, а затем lsв настоящее время расширен до lscи есть остановки расширения псевдонима, так как lscбыло первоначально расширяются. Итак, команда не работает, поскольку bash не знает других lsc.