Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: zsh 5.9 (macOS 15.8.2 Apple build): heredoc/here-string on a non-first pipeline member concatenates upstream pipe output into stdin instead of overriding the pipe
- X-seq: zsh-workers 55235
- From: Stephane Chazelas <stephane@xxxxxxxxxxxx>
- To: 孤客 <yfei087@xxxxxxxxx>
- Cc: zsh-workers@xxxxxxx
- Subject: Re: zsh 5.9 (macOS 15.8.2 Apple build): heredoc/here-string on a non-first pipeline member concatenates upstream pipe output into stdin instead of overriding the pipe
- Date: Sat, 31 Oct 2026 13:50:08 +0000
- Archived-at: <https://zsh.org/workers/55235>
- In-reply-to: <A143156B-84E8-4993-BFAE-C7BDAF0399EC@gmail.com>
- List-id: <zsh-workers.zsh.org>
- Mail-followup-to: 孤客 <yfei087@xxxxxxxxx>, zsh-workers@xxxxxxx
- References: <A143156B-84E8-4993-BFAE-C7BDAF0399EC@gmail.com>
2026-10-31 19:51:11 +0800, 孤客:
[...]
> > Minimal repro:
> >
> > % printf 'PIPE-CONTENT' | cat <<'EOF'
> > HEREDOC-CONTENT
> > EOF
> > PIPE-CONTENTHEREDOC-CONTENT # zsh 5.9 actual (concatenated)
> >
> > # expected / bash & /bin/sh actual:
> > HEREDOC-CONTENT
[...]
That's as documented. When the MULT_IOS option is enabled as
it is by default unless emulating other shells, if stdin is
redirected for reading more than once, stdin becomes a pipe
where the concatenation of all input sources is fed by a
background process.
Something similar is happening on the output side where where in
echo test > file | cmd
echo's stdout is made a pipe to a tee-like background process
that feeds the output to both `file` and `cmd`.
It's why
wc -l < *.txt
or
echo test >> $list_of_files
work for instance.
See:
info zsh multios
or https://zsh.sourceforge.io/Doc/Release/Redirection.html#Multios for details.
To get a POSIX-like behaviour, you can issue: set +o multios.
Here, you can also do:
% echo x | { cat <<< y; }
y
Or:
% echo x | cat <&- <<< y
y
In place of:
% echo x | cat <<< y
x
y
To make sure cat's stdin is only the y herestring.
If you're trying to have zsh interpret code written for sh, ksh or
bash, you may want to do that in sh or ksh (for ksh and bash)
emulation with:
emulate sh -c 'source the-sh-script'
For instance.
I have to admit that I disable that option in my ~/.zshrc, and
enable only when needed as I find that it gets in the way as
often as it's useful.
--
Stephane
Messages sorted by:
Reverse Date,
Date,
Thread,
Author