Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

In Bash, when specifying command line arguments to a command, what characters are required to be escaped?

Are they limited to the metacharacters of Bash: space, tab, ‘|’, ‘&’, ‘;’, ‘(’, ‘)’, ‘<’, or ‘>’?

share|improve this question
Don't forget (possible) filename globbing with * and ? – Jeff Schaller Mar 20 at 3:41
Thanks. Could you exhaustively list the kinds of characters which need to be escaped in cmd line args? – Tim Mar 20 at 3:48
The list is good to have, but the most important thing to understand about quoting, is: Everything between single quotes is passed literally and without word splitting. No exceptions. (This means there is no way whatsoever to embed a single quote within single quotes, by the way, but that's easy to work around.) – Wildcard Mar 20 at 8:19
up vote 14 down vote accepted

The following characters have special meaning to the shell itself in some contexts and may need to be escaped in arguments:

Some of those characters are used for more things and in more places than the one I linked.

There are a few corner cases that are explicitly optional:

Escaping a newline requires quoting — backslashes won't do the job. Any other characters listed in IFS will need similar handling. You don't need to escape ] or }, but you do need to escape ) because it's an operator.

Some of these characters have tighter limits on when they truly need escaping than others. For example, a#b is ok, but a #b is a comment, while > would need escaping in both contexts. It doesn't hurt to escape them all conservatively anyway, and it's easier than remembering the fine distinctions.

If your command name itself is a shell keyword (if, for, do) then you'll need to escape or quote it too. The only interesting one of those is in, because it's not obvious that it's always a keyword. You don't need to do that for keywords used in arguments, only when you've (foolishly!) named a command after one of them. Shell operators ((, &, etc) always need quoting wherever they are.

1Stéphane has noted that any other single-byte blank character from your locale also needs escaping. In most common, sensible locales, at least those based on C or UTF-8, it's only the whitespace characters above. In some ISO-8859-1 locales, U+00A0 no-break space is considered blank, including Solaris, the BSDs, and OS X (I think incorrectly). If you're dealing with an arbitrary unknown locale, it could include just about anything, including letters, so good luck.

Conceivably, a single byte considered blank could appear within a multi-byte character that wasn't blank, and you'd have no way to escape that other than putting the whole thing in quotes. This isn't a theoretical concern: in an ISO-8859-1 locale from above, that A0 byte which is considered a blank can appear within multibyte characters like UTF-8 encoded "à" (C3 A0). To handle those characters safely you would need to quote them "à". This behaviour depends on the locale configuration in the environment running the script, not the one where you wrote it.

I think this behaviour is broken multiple ways, but we have to play the hand we're dealt. If you're working with any non-self-synchronising multibyte character set, the safest thing would be to quote everything. If you're in UTF-8 or C, you're safe (for the moment).

share|improve this answer
Other blanks in your locale would need escaping as well (except currently the multi-byte one because of a bug) – Stéphane Chazelas Mar 20 at 7:25
You only need to escape ! when csh history expansion is enabled, typically not in scripts. [ ! -f a ] or find . ! -name... are fine. That's covered by your tighter limits section but maybe worth mentioning explicitly. – Stéphane Chazelas Mar 20 at 7:30
Note that there are contexts where other characters need quoting like: hash[foo"]"]=, ${var-foo"}"}, [[ "!" = b ]], [[ a = "]]" ]], the regexp operators for [[ x =~ ".+[" ]]. Other keywords than { (if, while, for...) would need to be quoted so they're not recognised as such... – Stéphane Chazelas Mar 20 at 7:48
To the extent that those are command-line arguments at all, the interpretation is up to the command in question (just like ]), so I'm not listing them. I don't think any keyword needs quoting in argument position. – Michael Homer Mar 20 at 8:02
Quoting builtins, dashes, or % doesn't do anything. – Michael Homer Mar 20 at 22:06

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.