Helvinion Helvinion - 3 years ago 246
Linux Question

Difference of interpretation of operator <<< between bash and zsh

In zsh,

echo -n "Hello " | cat - - <<< "World"

will print

Hello World

However in bash the same command will print


My interpretation is that in zsh cat will open a first file descriptor on stdin (first '-' option), read the piped "Hello", then close stdin, then somehow reopen it (second '-' option), then read the here-string "World", then conCATenate them into "Hello World".

But I do not understand what happens in bash. strace gave me weird results :

zsh $> echo -n "Hello " | strace cat - - <<< "World"
strace: Unknown pid: 7841
Process 7844 detached

bash $> echo -n "Hello " | strace cat - - <<< "World"
read(0, "World\n", 65536) = 6
write(1, "World\n", 6) = 6
read(0, "", 65536) = 0
fstat(0, {st_mode=S_IFREG|0600, st_size=6, ...}) = 0
fadvise64(0, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(0, "", 65536) = 0
close(0) = 0
close(1) = 0
close(2) = 0

cat just seems to ignore its second argument.

Any guru of bash/zsh to enlighten me please ? Is there a commun way to concatenate a stream wiht a string without any intermediate file or, if possible a here-document ?

Answer Source

Actually this has nothing to do with the second - argument to cat.

echo -n "Hello " | cat - <<< "World"

will have the same result.

The difference is the multios zsh option. You can check that after unsetopt multios zsh will behave in the same way as bash here.

Quoting the manual:

If the user tries to open a file descriptor for reading more than once, the shell opens the file descriptor as a pipe to a process that copies all the specified inputs to its output in the order specified, similar to cat, provided the MULTIOS option is set.

So in your example the shell will concatenate the data from the pipe and the here-sting together and pipe it to cat's input.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download