bash "wc -l" 如果调用或通过 tee 命令输出不同
bash "wc -l" command output differs if call or through tee
当我在 Bash 中发出两个等效命令时,我得到了不同的输出(来自 "wc -l" 命令),见下文:
root@devel:~# ls /usr/bin -lha | tee >(wc -l) >(head) > /dev/null
total 76M
drwxr-xr-x 2 root root 20K Nov 11 18:58 .
drwxr-xr-x 10 root root 4.0K Oct 8 15:31 ..
-rwxr-xr-x 1 root root 51K Feb 22 2017 [
-rwxr-xr-x 1 root root 96 Jan 19 2017 2to3-3.5
-rwxr-xr-x 1 root root 23K Mar 22 2017 addpart
lrwxrwxrwx 1 root root 26 May 10 2017 addr2line -> x86_64-linux-gnu- addr2line
lrwxrwxrwx 1 root root 6 Dec 13 2016 apropos -> whatis
-rwxr-xr-x 1 root root 15K Sep 13 19:47 apt
-rwxr-xr-x 1 root root 79K Sep 13 19:47 apt-cache
137
root@devel:~# ls /usr/bin -lha | wc -l
648
我错过了什么?
这很奇怪,但是当我这样调用它时,它会得到更奇怪的输出:
root@devel:~# ls /usr/bin -lha | tee >(wc) >(wc) > /dev/null
648 6121 39179
648 6121 39179
root@devel:~# ls /usr/bin -lha | tee >(wc) >(wc) > /dev/null
648 6121 39179
648 6121 39179
root@devel:~# ls /usr/bin -lha | tee >(wc) >(wc -l) > /dev/null
648
root@devel:~# 648 6121 39179
似乎是命令 运行 异步并在不同的时间结束...或者它可能是什么?
简单回答:
如何修复:
ls /usr/bin -lha | tee <b>--output-error=exit-nopipe</b> >(wc -l) >(head) > /dev/null
详情:
命令head
只打印输入的头部,所以只要输入足够就可以完成它的工作,然后退出而不等待所有输入。
所以让我们用简单的 "head"
.
替换命令 head
ls /usr/bin -lha | tee >(wc -l) <b>>(read l; echo $l)</b> > /dev/null
简单的 "head"
将只读取一行,然后退出,这会导致管道文件在 tee
完成向其传输所有数据之前立即关闭。
所以毫无疑问,你会得到与简单 "head"
相同的结果。 wc
仍然打印错误数字。
你的问题的根本原因,我想你可以自己得出结论,是 tee
的输出管道之一较早关闭,tee
遇到 写入错误,然后停止写入其他输出文件。
了解了根本原因后,我想您将很容易理解手册页中的以下部分。
MODE determines behavior with write errors on the outputs:
'warn' diagnose errors writing to any output
'warn-nopipe'
diagnose errors writing to any output not a pipe
'exit' exit on error writing to any output
'exit-nopipe'
exit on error writing to any output not a pipe
The default MODE for the -p option is 'warn-nopipe'. The default operation
when --output-error is not specified, is to exit immediately on error writing to
a pipe, and diagnose errors writing to non pipe outputs.
一些多余的话
实际上,如果您在有问题的命令行中将 >(wc -l)
替换为常规文件,您会发现文件大小始终为 16384 或 20480 或 32768 或 36864 或 28672 或...,所有这些是 4096 的倍数。(写入常规文件未完成,因为 tee
提前中止。如果写入完成,文件大小将是任意值。)
4096 是大多数类 UNIX 系统的 PIPE_BUF
的值。如果你知道PIPE_BUF
是什么,你就会很容易理解为什么文件大小总是4096的倍数。
当我在 Bash 中发出两个等效命令时,我得到了不同的输出(来自 "wc -l" 命令),见下文:
root@devel:~# ls /usr/bin -lha | tee >(wc -l) >(head) > /dev/null
total 76M
drwxr-xr-x 2 root root 20K Nov 11 18:58 .
drwxr-xr-x 10 root root 4.0K Oct 8 15:31 ..
-rwxr-xr-x 1 root root 51K Feb 22 2017 [
-rwxr-xr-x 1 root root 96 Jan 19 2017 2to3-3.5
-rwxr-xr-x 1 root root 23K Mar 22 2017 addpart
lrwxrwxrwx 1 root root 26 May 10 2017 addr2line -> x86_64-linux-gnu- addr2line
lrwxrwxrwx 1 root root 6 Dec 13 2016 apropos -> whatis
-rwxr-xr-x 1 root root 15K Sep 13 19:47 apt
-rwxr-xr-x 1 root root 79K Sep 13 19:47 apt-cache
137
root@devel:~# ls /usr/bin -lha | wc -l
648
我错过了什么?
这很奇怪,但是当我这样调用它时,它会得到更奇怪的输出:
root@devel:~# ls /usr/bin -lha | tee >(wc) >(wc) > /dev/null
648 6121 39179
648 6121 39179
root@devel:~# ls /usr/bin -lha | tee >(wc) >(wc) > /dev/null
648 6121 39179
648 6121 39179
root@devel:~# ls /usr/bin -lha | tee >(wc) >(wc -l) > /dev/null
648
root@devel:~# 648 6121 39179
似乎是命令 运行 异步并在不同的时间结束...或者它可能是什么?
简单回答:
如何修复:
ls /usr/bin -lha | tee <b>--output-error=exit-nopipe</b> >(wc -l) >(head) > /dev/null
详情:
命令head
只打印输入的头部,所以只要输入足够就可以完成它的工作,然后退出而不等待所有输入。
所以让我们用简单的 "head"
.
head
ls /usr/bin -lha | tee >(wc -l) <b>>(read l; echo $l)</b> > /dev/null
简单的 "head"
将只读取一行,然后退出,这会导致管道文件在 tee
完成向其传输所有数据之前立即关闭。
所以毫无疑问,你会得到与简单 "head"
相同的结果。 wc
仍然打印错误数字。
你的问题的根本原因,我想你可以自己得出结论,是 tee
的输出管道之一较早关闭,tee
遇到 写入错误,然后停止写入其他输出文件。
了解了根本原因后,我想您将很容易理解手册页中的以下部分。
MODE determines behavior with write errors on the outputs:
'warn' diagnose errors writing to any output
'warn-nopipe'
diagnose errors writing to any output not a pipe
'exit' exit on error writing to any output
'exit-nopipe'
exit on error writing to any output not a pipe
The default MODE for the -p option is 'warn-nopipe'. The default operation
when --output-error is not specified, is to exit immediately on error writing to
a pipe, and diagnose errors writing to non pipe outputs.
一些多余的话
实际上,如果您在有问题的命令行中将 >(wc -l)
替换为常规文件,您会发现文件大小始终为 16384 或 20480 或 32768 或 36864 或 28672 或...,所有这些是 4096 的倍数。(写入常规文件未完成,因为 tee
提前中止。如果写入完成,文件大小将是任意值。)
4096 是大多数类 UNIX 系统的 PIPE_BUF
的值。如果你知道PIPE_BUF
是什么,你就会很容易理解为什么文件大小总是4096的倍数。