2
  1. printf "%s" `echo ../.. | sed 's/[.]/\\&/g'`
  2. printf "%s" $(echo ../.. | sed 's/[.]/\\&/g')
  3. printf "%s" "$(echo ../.. | sed 's/[.]/\\&/g')"
ilkkachu
  • 138,973

1 Answers1

3

As far as I can see, none, in this particular case, with the string ../...

Between the two second and third ones, there's not much difference with or without the quotes with that particular input, the string ../... But if the output from the command substitution contained white space or glob characters, there would be a difference, compare:

$ mkdir temp; cd temp; touch hello.txt
$ printf "%s" $(echo "foo * bar"); echo
foohello.txtbar
$ printf "%s" "$(echo "foo * bar")"; echo
foo * bar

See: What's the right way to quote $(command $arg)?


The one with backticks is a deprecated version of $(...), and works differently wrt. quoting and escaping. Within the backticks, unlike with $(...), one set of backslashes is used up for the command substitution, so you get a different result with that. (\\& turns to \&, which makes makes sed print the literal &, as & itself is special to sed and the remaining backslash removes the special meaning.)

See: What's the difference between $(stuff) and `stuff`?


Additionally, Bash 5.0 had a bug/misfeature where a presence of a backslash was enough to have a string get treated as a glob, even if it didn't contain other, actual glob characters.

The result of the unquoted expansion in the second command would be treated as a glob, and \.\./\.\. would turn into ../.. in the same way e.g. .[.]/.[.] or .?/.? would. (The pathname ../.. should always exist, even in /. Of course .?/.? could match other names, too.)

Similarly, failglob might be triggered:

bash-5.0.3$ shopt -s failglob
bash-5.0.3$ echo $(echo 'xxxxxx\x')
bash5.0.3: no match: xxxxxx\x

(But just echo xxxxxx\x doesn't do it.)

See the Bash-5.1-beta announcement and e.g. this bug report on the bug-bash mailing list.

ilkkachu
  • 138,973