How to properly nest Bash backticks
BashShellUnixQuotingBash Problem Overview
Either I missed some backlash or backlashing does not seem to work with too much programmer-quote-looping.
$ echo "hello1-`echo hello2-\`echo hello3-\`echo hello4\`\``"
hello1-hello2-hello3-echo hello4
Wanted
hello1-hello2-hello3-hello4-hello5-hello6-...
Bash Solutions
Solution 1 - Bash
Use $(commands)
instead:
$ echo "hello1-$(echo hello2-$(echo hello3-$(echo hello4)))"
hello1-hello2-hello3-hello4
$(commands)
does the same thing as backticks, but you can nest them.
You may also be interested in Bash range expansions:
echo hello{1..10}
hello1 hello2 hello3 hello4 hello5 hello6 hello7 hello8 hello9 hello10
Solution 2 - Bash
if you insist to use backticks, following could be done
$ echo "hello1-`echo hello2-\`echo hello3-\\\`echo hello4\\\`\``"
you have to put backslashes, \\ \\\\ \\\\\\\\
by 2x and so on, its just very ugly, use $(commands)
as other suggested.
Solution 3 - Bash
Any time you want to evaluate a command use command substitution
:
$(command)
Any time you want to evaluate an arithmetic expression use expression substitution
:
$((expr))
You can nest these like this:
Let's say file1.txt is 30 lines long and file2.txt is 10 lines long, than you can evaluate an expression like this:
$(( $(wc -l file1.txt) - $(wc -l file2.txt) ))
which would output 20 ( the difference in number of lines between two files).
Solution 4 - Bash
It's a lot easier if you use bash's $(cmd)
command substitution syntax, which is much more friendly to being nested:
$ echo "hello1-$(echo hello2-$(echo hello3-$(echo hello4)))"
hello1-hello2-hello3-hello4
Solution 5 - Bash
Sometimes backtick nesting can be substituted with xargs
and pipes
$ echo hello4 | xargs echo hello3 | xargs echo hello2 | xargs echo hello1
hello1 hello2 hello3 hello4
Drawback of this solution are:
-
All arguments must be provided in reverse order (4→1);
-
All arguments become space separated (solvable with
tr
):$ echo hello4 | xargs echo hello3 | xargs echo hello2 | xargs echo hello1 | tr ' ' '-' hello1-hello2-hello3-hello4
Let's show a real use-case.
Following commands work in bash, but not in tcsh (backtick nesting is not handled very good in tcsh)
$ ls $(dirname $(which bash))
$ ls `dirname \`which bash\``
They can be substituted with
$ which bash | xargs dirname | xargs ls
Solution 6 - Bash
You can capture and combine into a variable incrementally
__=`printf hello2-`
__=`printf "${__}hello3-"`
__=`printf "${__}hello4-"`
printf "hello1-${__}"