Reputation: 87
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
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
Reputation: 41
You can do that where the command is your command you want like echo
:
echo "Hello " | COMMAND "$(cat -)World"
Upvotes: 0