Unix & Linux Asked on August 2, 2020
A common way to skip aliases is to add a backslash before the aliased command.
$ alias ls='ls -l' $ ls file -rw-r--r-- 1 user user 70 Jul 30 14:37 file $ ls file file
My research has led me to discover other exotic ways to skip aliases, such as
But where is that behavior documented, or (put another way) why is that the correct behavior? The POSIX specification does not seem to
document any special case which deactivates aliases when preceding them
with a backslash. I also could not find it in my shell manual.
This is a self-answered question.
The bash manual does document it. My emphasis:
The first word of each simple command, if unquoted, is checked to see if it has an alias.
In the mksh manual:
The alias expansion process stops (…) when a quoted word is found
In the zsh manual:
Alias expansion is done on the shell input before any other expansion except history expansion. Therefore, if an alias is defined for the word foo, alias expansion may be avoided by quoting part of the word, e.g.
foo. Any form of quoting works, although there is nothing to prevent an alias being defined for the quoted form such as
That's better than the dash manual and the ksh manual. The dash manual describes quoting before reserved words and aliases and doesn't describe the interaction between them. The ksh manual states that reserved words are only recognized when not quoted, but doesn't state this for aliases.
Historically, I think this arose partly as a language design choice and partly to simplify implementation. The Bourne shell didn't have aliases, but it did have the behavior that reserved words are only recognized when not quoted. This makes sense because the parser needs to know whether a word is a reserved word early on. In particular, it would be problematic to treat the result of a variable or command substitution as a reserved word. Consider:
if condition then command1 "$else_or_not_else" command2 fi
condition is false and the value of
else_or_not_else happens to be
command2 be executed? That would require the parser to expand
$else_or_not_else — but this part of the code is skipped since
condition is false! If `"else" had to be recognized as a keyword, the shell parser would need to have a mode where it processes quoting but not substitutions, which would add another layer of complexity.
Recognizing aliases coming from substitutions would also be problematic. An alias could be something like
alias a='command1; $command2'
; in the alias is a command separator which the parser needs to take into account. If alias expansion happened after variable substitution, the parser would need to be invoked again after variable substitution. In addition, variable substitution would need to be invoked a second time on the expansion of the alias. So it simplifies both the language design and the interpreter implementation to not recognize aliases coming from substitution. And once again, it's easier to keep quoting and substitution together, both for users to understand the language and for implementers to make an interpreter.
Keeping the same rules for reserved words and aliases is also a simplification factor.
Answered by Gilles 'SO- stop being evil' on August 2, 2020
The key is that the shell performs Alias Substitution (section 2.3.1) before applying Shell Grammar rules (section 2.10). The first step is Token Recognition (section 2.3):
2.3 Token Recognition
The token shall be from the current position in the input until a token is delimited according to one of the rules below; the characters forming the token are exactly those in the input, including any quoting characters.
(...Rules of delimiting tokens...)
Once a token is delimited, it is categorized as required by the grammar in Shell Grammar.
2.3.1 Alias Substitution
After a token has been delimited, but before applying the grammatical rules in Shell Grammar, a resulting word that is identified to be the command name word of a simple command shall be examined to determine whether it is an unquoted, valid alias name.
From the bold parts, we conclude that upon reaching the alias lookup step, the quoting has not been removed. (Escaping with a backslash is also quoting.)
ls means that the shell will look for an alias with
that exact literal name, i.e.,
ls. Such alias names are not even
possible, so the alias expansion does not happen
and the shell passes on to the Grammar Rules,
at which point
both are resolved to our old-friend
ls, since "a <backslash> that is not quoted shall preserve the literal value
of the following character". If the PATH shell variable is the ordinary one,
/bin/ls is executed without the
That also explains
l''s, ... skip the alias.
Answered by Quasímodo on August 2, 2020
1 Asked on February 10, 2021
0 Asked on February 10, 2021 by divb
0 Asked on February 10, 2021 by coffeecatde
1 Asked on February 9, 2021 by luwachamohh
1 Asked on February 9, 2021 by isarandi
2 Asked on February 8, 2021 by nanor
9 Asked on February 8, 2021
2 Asked on February 7, 2021 by prisoner-13
1 Asked on February 7, 2021 by chiseledabs
1 Asked on February 6, 2021 by linuxsecurityfreak
0 Asked on February 6, 2021
1 Asked on February 5, 2021 by robert-einsle
3 Asked on February 5, 2021 by s55michi
0 Asked on February 5, 2021 by modernneo
1 Asked on February 5, 2021 by perimosh
1 Asked on February 5, 2021 by pro-backup
Get help from others!