Helvinion
Helvinion

Reputation: 87

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

World

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 ?

Upvotes: 3

Views: 190

Answers (2)

Michał Politowski
Michał Politowski

Reputation: 4385

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.

Upvotes: 4

MadSquirrel
MadSquirrel

Reputation: 41

You can do that where the command is your command you want like echo:

echo "Hello " | COMMAND "$(cat -)World"

Upvotes: 0

Related Questions