0

Foreword: I've already seen possibly related question Difference between 'ls' and 'echo $(ls)'

Does bash perform word splitting on output capturing? This guide -- mywiki.wooledge.org/WordSplitting says "no":

Word splitting is not performed on expansions in assignments. Thus, one does not need to quote anything in a command like these: [...] bar=$(a command)

But when I do res=$(find); echo $res output differs from just find:

$ find
.
./file2
./file1
./test.sh
$ res="$(find)"; echo $res
. ./file2 ./file1 ./test.sh
$ res=$(find); echo $res
. ./file2 ./file1 ./test.sh

 
9
  • Cannot reproduce with GNU bash, version 5.0.18(1)-release (x86_64-slackware-linux-gnu) Sep 27, 2020 at 20:23
  • The the text that you quote does not apply to the output that you see, which is produced by echo. You may want to try echo "$res".
    – Kusalananda
    Sep 27, 2020 at 20:34
  • @thanasisp sorry, I found out that firstly I used zsh as a shell :-D
    – aryndin
    Sep 27, 2020 at 20:35
  • 1
    When bash processes an unquoted variable reference (e.g. echo $res), it'll word-split the result (assuming default options). zsh does not do this (again assuming default options). Sep 27, 2020 at 20:37
  • 1
    @The splitting doesn't happen in res=$(find), but it does in echo $res. See this question and its answer. Personally, I think it's easier to just double-quote all variable and command substitutions, rather than trying to keep track of where it's safe to omit the quotes and where it can cause trouble. Sep 27, 2020 at 22:48

1 Answer 1

4

Note that the text that you quote only relates to the assignment to your variable res. There is no issue with that part.

The find utility produces newline-delimited pathnames as output, as you show.

Assigning this output to a variable will retain the newlines (except for the last, which is removed).

It's all good so far, but then...

When you call echo with your unquoted variable in bash, the variable's value is split on spaces, tabs and newlines (by default), and the resulting strings undergo filename generation (globbing). The resulting words are then given as individual arguments to echo.

The echo utility will output its arguments delimited by space characters (and add a newline at the end). This is what you show happens with echo $res.

To see the value of the variable without letting the shell split it into multiple words and do filename globbing on them, double quote the variable's expansion: echo "$res", or even better, printf '%s\n' "$res" (see Why is printf better than echo?).

In short, the expansion of the variable in the call to echo must be quoted.

You must log in to answer this question.

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