Zsh 为什么可以不消耗管道中间的标准输出?

要从十来年前的一个老 U 盘拷贝文件,数据传输速度慢(20MB/s),需要监控下进程:

➜  qqsrx git:(main) du -h /Volumes/USB/database.sqlite
712M	/Volumes/USB/database.sqlite
➜  qqsrx git:(main) wc -c /Volumes/USB/database.sqlite
 746926080 /Volumes/USB/database.sqlite
➜  qqsrx git:(main) cat /Volumes/USB/database.sqlite | pv -s 746926080 | > ./database/database.sqlite cat
 712MiB 0:00:29 [24.0MiB/s] [=====================================================================>] 100%

cat 读取文件内容,pv 监控速度,再用 cat 读取标准输入,配合重定向写入目标文件。

上面的方法可行,但我发现一个关于 Zsh 奇怪的问题:

➜  qqsrx git:(main) echo $0
-zsh
➜  qqsrx git:(main) date | > /dev/null cat | nl
     1	Fri Oct 28 22:43:45 CST 2022

明明 date 的输出已经被 cat 消耗了,为啥 nl 还能读取到呢?这是 Zsh 的一个 Feature 吗?

Bash 符合我的预期:

➜  qqsrx git:(main) bash

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
bash-3.2$ date | > /dev/null cat | nl
bash-3.2$ date | tee /dev/null | nl
     1	Fri Oct 28 22:34:46 CST 2022
bash-3.2$ exit

这个功能叫 multios。

2 个赞