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



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