29

In the first part of my question I will provide some background info as a service to the community. The second part contains the actual question.

Part I

Assume I've created the following alias:

alias ls='ls -r'

I know how to temporarily unalias (i.e., override this alias) in the following ways, using:

1) the full pathname of the command: /bin/ls

2) command substitution: $(which ls)

3) the command builtin: command ls

4) double quotation marks: "ls"

5) single quotation marks: 'ls'

6) a backslash character: \ls

Case 1 is obvious and case 2 is simply a variation. The command builtin in case 3 was designed to ignore shell functions, but apparently it also works for circumventing aliases. Finally, cases 4 and 5 are consistent with both the POSIX standard (2.3.1):

"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."

and the Bash Reference Manual (6.6):

"The first word of each simple command, if unquoted, is checked to see if it has an alias."

Part II

Here's the question: why is case 6 (overriding the alias by saying \ls) considered quoting the word? In keeping with the style of this question, I am looking for references to the "official" documentation.

The documentation says that a backslash only escapes the following character, as opposed to single and double quotation marks, which quote a sequence of characters. POSIX standard (2.2.1):

"A backslash that is not quoted shall preserve the literal value of the following character, with the exception of a < newline >"

Bash Reference Manual (3.1.2.1):

"A non-quoted backslash ‘\’ is the Bash escape character. It preserves the literal value of the next character that follows, with the exception of newline."

(BTW, isn't "the next character that follows" a bit of overkill?)

A possible answer might be that this situation isn't that special: it is similar to a few cases in ANSI-C quoting, e.g. \nnn. However, that is still escaping a single character (the eight-bit character whose value is the octal value nnn), not a sequence of characters.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Alexandros Gezerlis
  • 2,221
  • 16
  • 21
  • just note: the 6th is different from the first 5 : the first 5 bypass both function AND alias, whereas `\ls` will (in bash) only bypass the alias, NOT a function of the same name. ie : `alias ls='echo "aliased"' ; function ls { echo "function" ; } ; ls ; \ls ; command ls` : the first (ls) will show "aliased", the 2nd (\ls) bypasses only the alias and therefore shows "function", and the 3rd (command ls) shows the output of regular ls – Olivier Dulac Sep 10 '13 at 17:30
  • This is a great question but none of the explanations seem to clear up any confusion I have on the matter. @alexandros-gezerlis, if you've been able to comprehend the reason, can you spell it out for me (the folks at home)? – harperville Dec 21 '16 at 19:11
  • @OlivierDulac 5 does not bypass function at least in GNU bash 4.3.11 – jarno Jun 11 '17 at 11:25

3 Answers3

5

Historically, and maintained by POSIX, quoting any part of the word causes the entire word to be considered quoted for the purposes of functions and alias expansion. It also applies to quoting the end token for a here document:

cat << \EOF
this $text is fully quoted
EOF
geekosaur
  • 59,309
  • 11
  • 123
  • 114
  • Thanks. I have edited the question (first paragraph in Part II) to clarify what I had mistakenly thought was obvious: I would appreciate a specific citation. – Alexandros Gezerlis May 28 '11 at 16:48
  • Also, I just noticed that POSIX 2.7.4 on here-documents explicitly states the case of escaping: "If any character in word is quoted, the delimiter shall be formed by performing quote removal on word". However, in the general section on token recognition (POSIX 2.3) it is clearly stated that here-documents are special: "These lines shall be parsed using two major modes: ordinary token recognition and processing of here-documents." – Alexandros Gezerlis May 28 '11 at 17:02
  • @Alexandros: those are both a bit ambiguous. You want to read a little farther into section 2.7.4, right after your first quotation: "If no characters in word are quoted, all lines of the here-document shall be expanded for parameter expansion, command substitution, and arithmetic expansion. In this case, the backslash in the input behaves as the backslash inside double-quotes (see Double-Quotes). However, the double-quote character ( '"' ) shall not be treated specially within a here-document, except when the double-quote appears within "$()", "``", or "${}"." – geekosaur May 28 '11 at 18:05
  • @geekosaur: sorry, but I don't see how that is related. I don't understand how the sentence you quote (discussing the case where no characters in word are quoted) is relevant to your example, in which the first character in word *is* quoted, which is presumably the reason why there's no parameter expansion taking place. Your example also works with E\OF. Finally, I still don't see how all this extends beyond here-documents, especially given my second quotation. – Alexandros Gezerlis May 28 '11 at 19:05
  • Even though what I just wrote is correct, it got me thinking: I tried my original example, and l\s works the same way that \ls does. (Similarly, 'l's, l's', "l"s, and l"s" also work.) This is consistent with what you write in your answer and what is quoted in the here-document documentation, but I don't see a reason why it should extend beyond here-documents. – Alexandros Gezerlis May 28 '11 at 19:27
  • 2
    A random side note: apparently (at least in the shells I've tried this in), having an empty pair of quote marks somewhere in the word counts as quoting part of the word (examples: `''ls`, `l""s`, and `cat < – Gordon Davisson May 28 '11 at 22:17
4

Just for completion, here's yet another way to suppress alias & function lookups (by clearing the entire shell environment for a single command):

# cf. http://bashcurescancer.com/temporarily-clearing-environment-variables.html
env -i ls
karl
  • 49
  • 1
-1

\ls only quotes the first character rather than the whole word. It's equivalent to writing 'l's.

You can verify it like this:

$ touch \?l
$ \??
bash: ?l: command not found

If \?? quoted the whole word it would say ?? not found rather than ?l not found.

I.e. it has the same effect as:

$ '?'?
bash: ?l: command not found

rather than:

$ '??'
bash: ??: command not found
Snippy
  • 1