Why doesn't alias foo='echo "This is a quote: \'"' work?
This is zsh
, man, not fish
.
In zsh
, like in every Bourne-like shell (and also csh
), single quotes are strong quotes, there is no escaping within them (except by using the rcquotes
options as hinted by @JdeBP where zsh
emulates rc
quotes¹). You cannot have a single quote inside a single-quoted string, you need first to close the single quoted string and enter the literal single quote using another quoting mechanism (like \
or "
):
alias shopt='echo "You'\''re looking for setopt. This is Z shell, man, not Bash."'
Or:
alias shopt='echo "You'"'"'re looking for setopt. This is Z shell, man, not Bash."'
Though you could also do:
alias shopt="echo \"You're looking for setopt. This is Z shell, man, not Bash.\""
("..."
are weaker quotes inside which several characters, including \
(here used to escape the embedded "
) are still special).
Or:
alias shopt=$'echo "You\'re looking for setopt. This is Z shell, man, not Bash."'
($'...'
is yet another kind of quotes from ksh93, where the '
can be escaped with \'
).
(and BTW, you can also use the standard set -o
in place of setopt
in zsh
. bash
, for historical reasons, has two sets of options, one that you set with set -o
one with shopt
; zsh
like most other shells has only one set of options).
¹ In rc
, the shell of Plan9, with a version for unix-likes also available, single quotes are the only quoting mechanism (backslash and double quotes are ordinary characters there), the only way to enter a literal single-quote there is with ''
inside single quotes, so with zsh -o rcquotes
, you could do:
alias shopt='echo "You''re looking for setopt. This is Z shell, man, not Bash."'
shopt='echo "You\'
This is not voodoo. This is normal POSIX shell quoting in action. There is no escaping mechanism within single-quoted strings. They always terminate at the next single quote. There is a Z shell extension that makes two successive single-quoted strings get a single quote placed between them, which you could employ. Or you could just terminate the single-quoted string, use an escaped (or indeed non-single-quote quoted) single quote, and then start a second single-quoted string.
Or you could not use contractions in your messages. ☺
Further reading
- "Single quotes". Shell command language. Base Specifications. IEEE 1003.1:2017. The Open Group
- "Quoting". Shell Grammar. The Z Shell manual.
The other answers do a good job of explaining why you're seeing this behavior. But if I may make a suggestion for how to actually solve this problem:
Don't use aliases for anything even remotely complicated.
Sure, you can tie your brain up in knots trying to figure out how to nest N layers of quotes, but it's rarely worth it for an alias. When an alias is complicated enough that its quoting becomes nontrivial, just switch to a shell function:
shopt(){
echo "You're looking for setopt. This is Z shell, man, not Bash."
}
This removes an entire layer of quotes, allows you to add more code to the shell function later, and is generally much easier to read. It also allows much finer control over how and where arguments are inserted, instead of the alias approach of "just replace the beginning of the line and let the remaining words fall where they may." For example, with your (corrected) alias, if you type this:
shopt -s some_opt
...then you will get this output:
You're looking for setopt. This is Z shell, man, not Bash. -s some_opt
That's probably not what you wanted. The shell function will consume whatever arguments you pass to it, and silently discard them.