Bash Alias - Precedence/Shadowing (/hiding/failing)
Bash does allow aliases to contain aliases but it has built-in protections against infinite loops. In your case, when you type lsc
, bash first expands the alias to:
ls -Flatr --color=always
Since ls
is also an alias, bash expands it to:
lsc -Flatr --color=always
lsc
is an alias but, quite sensibly, bash refuses to expand it a second time. If there was a program named lsc
, bash would run it. But, there is not and that is why you get command not found
.
Addendum
It is different when lscR
runs. lscR
expands to:
ls -FlatrR --color=always
Since ls
is an alias, this expands to:
lsc -FlatrR --color=always
Since lsc
is an alias, this expands to:
ls -Flatr --color=always -FlatrR --color=always
Since ls
has already been expanded once, bash refuses to expand it a second time. Since a real command called ls
exists, it is run.
History
As noted by Schily in the comments, bash borrowed the concept of not expanding an alias a second time from ksh.
Aside
Aliases are useful but not very powerful. If you are tempted to do something complex with an alias, such as argument substitution, don't; use a shell function instead.
From the bash manual:
The first word of the replacement text is tested for aliases, but a word that is identical to an alias being expanded is not expanded a second time. This means that one may alias
ls
to "ls -F
", for instance, and Bash does not try to recursively expand the replacement text.
In the ls
alias, ls
is expanded to lsc
and then again to ls -Flatr --color=always
, and there the alias expansion stops, since ls
was originally being expanded. So, the command runs fine, ls
now being resolved to an external command.
In the lsc
alias, lsc
is expanded to ls -Flatr --color=always
, and then ls
is now expanded to lsc
and there the alias expansion stops, since lsc
was originally being expanded. So, the command fails, since bash doesn't know of any other lsc
.