Это эффект MULTIOS .
echo foo >&2 | grep foo
напишет fooв stderr, а также трубу fooк grep. Так как stderr по умолчанию использует терминал, вы увидите две fooстроки, одну из которых echo, одну из grepрезультата.
{ echo foo >&2 | grep foo } >/dev/null
Здесь вы видели одну строку, потому что stdout был перенаправлен на /dev/null, вы видели только fooстроку с echo.
{ echo foo >&2 | grep foo } 2>/dev/null
Здесь вы видели одну строку, потому что stderr был перенаправлен на /dev/null, вы видели только fooстроку с grep.
Вы можете легко увидеть разницу в терминале по цвету линейного выхода. grepвыделит соответствующий шаблон (или вы можете принудительно его использовать --color=always).
MULTIOSбыл включен по умолчанию с nomultiosопцией unset:
$ unsetopt | grep nomultios
nomultios
Чтобы отключить его, просто установите nomultiosопцию:
$ setopt nomultios
{echo foo >&2} | grep foo, если вы видите, что я пытаюсь сказать. Я думал, что команда, о которой я спрашивал выше, перенаправит stdout в stderr, а затем перенаправит пустой stdout в grep.