Passing untrusted text to a shell is dangerous: spaces split it into multiple
arguments and characters like ;, |, and backtick can run commands. This tool
wraps a value into one inert, shell-safe argument using POSIX single-quoting.
How it works
The whole value is wrapped in single quotes, inside which every character is
literal. The only character that cannot appear inside single quotes is the single
quote itself, so each one is rewritten as the four-character sequence '\'':
hello world -> 'hello world'
O'Brien -> 'O'\''Brien'
rm -rf /; ls -> 'rm -rf /; ls' (semicolon is now literal)
(empty) -> '' (one empty argument)
The shell concatenates adjacent quoted and escaped pieces back into the exact original string, while never interpreting any of its characters as syntax.
Why single quotes rather than double quotes
A common misconception is that double quotes are equally safe. They are not.
Inside double quotes the shell still expands $variable, $(command), `backtick`,
and \ sequences. So a user-supplied value like $(rm -rf /) passed inside double
quotes would be executed. Single quotes suppress all of this — every character is
literally passed through, making them the correct choice for untrusted data.
The '\'' pattern demystified
The sequence looks strange at first glance. Breaking it apart:
'closes the current single-quoted section.\'is a backslash-escaped single quote outside any quotes, producing a literal single-quote character.'opens a new single-quoted section for the rest of the string.
The shell joins these three pieces and the result is the original string with an
embedded single quote. For example O'Brien becomes 'O'\''Brien', which is
three shell tokens that the shell reassembles into one argument value: O'Brien.
When shell escaping is not enough
Single-quoting handles one argument correctly, but if you are building a full
command string from several user-supplied pieces and then passing that string to
eval or a remote shell, you need to escape each piece individually. Chaining
multiple escaped pieces together in one command string is safe as long as the
overall structure is fixed in your code and the variable data appears only inside
the individually escaped tokens.
For complex scenarios — especially when the shell command is constructed in a loop or involves many variables — consider passing data out-of-band instead:
- Environment variables (
ENV_VAR="$value" command) keep untrusted data entirely outside the command-line parsing step. - Stdin (
printf '%s\n' "$value" | command --input-from-stdin) avoids argument construction entirely. - Language-native subprocess APIs (
subprocess.run(["cmd", arg])in Python) skip the shell entirely and are always safer than building a command string.
Tips and notes
Single quotes beat double quotes for safety because double quotes still expand
$, backtick, and \. The '\'' idiom looks odd but is the canonical,
portable way to embed a quote — it works in sh, Bash, Zsh, and Dash alike. Always
quote the empty string as '' so it survives word-splitting as a real empty
argument. Use this whenever you build a command line from variable data; for
larger scripts, prefer arrays or passing data via environment or stdin instead.