How to properly nest Bash backticks

BashShellUnixQuoting

Bash 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-${__}"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionhhhView Question on Stackoverflow
Solution 1 - BashJoey AdamsView Answer on Stackoverflow
Solution 2 - BashYOUView Answer on Stackoverflow
Solution 3 - BashEtienne LawlorView Answer on Stackoverflow
Solution 4 - BashMark RushakoffView Answer on Stackoverflow
Solution 5 - BashG. C.View Answer on Stackoverflow
Solution 6 - BashCervEdView Answer on Stackoverflow