Say I have to use quotes to encapsulate subshell output like:

DATA="$(cat file.hex | xxd -r)"

But I need to nest this kind of stuff like:

DATA="$(cat file.hex | xxd -r | tr -d \"$(cat trim.txt)\")"

I can't use single quotes because those do not expand variables that are inside of them. Escaping quotes doesn't work because they are just treated as passive text.

How do I handle this?

  • 1
    Why don't you use DATA="$(cat file.hex | xxd -r | tr -d "$(cat trim.txt)")"?
    – cuonglm
    Jun 8, 2015 at 18:22

3 Answers 3


You don't need to escape the quotes inside a subshell, since the current shell doesn't interpret them (it doesn't interpret anything from $( to ), actually), and the subshell doesn't know about any quotes that are above.

Quoting a subshell at variable assignment is unnecessary too, for more info see man bash.

  • 1
    It depends on what you're trying to do, but it's usually a best practice. See github.com/koalaman/shellcheck/wiki/Sc2086
    – LPCRoy
    Nov 2, 2015 at 17:15
  • 3
    Why is quoting a subshell at variable assignment unnecessary?
    – jmrah
    Jun 25, 2020 at 17:54
  • So if I want to have a ) in the subcommand, should I escape the )?
    – Pedro A
    Jul 2, 2021 at 2:04
  • 1
    My man bash says "If the substitution appears within double quotes, word splitting and pathname expansion are not performed on the results." (in EXPANSION > Command Substitution). That seems to imply that we would need to quote subshell invocations.
    – palswim
    Sep 3, 2021 at 18:13

You don't need to escape the nested quotes inside. They get parsed properly, surprisingly!

DATA="$(cat file.hex | xxd -r | tr -d "$(cat trim.txt)")"
  • Indeed, it is very disturbing that it works so simply ! As for literal quotes, the usual rule still applies : triple it, backslash the middle one (a"b --> a"\""b).
    – Lenormju
    Sep 1, 2022 at 6:40

I just had success by treating the $() as quoting subshell's stdout, so I only have to use the inner quotes on the variable's expansion:

# Part of an MSys2 reimplementation of realpath, hence the `-W`
input="../../My Programs"
output=$(cd "$input"; pwd -W) 
echo "$output"

The space in My Programs is preserved and no rogue quote marks appear in output

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .