简体   繁体   English

bash“wc -l”命令输出在呼叫或通过tee时有所不同

[英]bash “wc -l” command output differs if call or through tee

When I issued two equivalent commands in Bash I got different output (from "wc -l" command), see below: 当我在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

what am I missing? 我错过了什么?

it's strange, but when I call it this way it gets even stranger output: 这很奇怪,但是当我以这种方式调用它时,它会输出更奇怪的输出:

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

seems like commands running asynchronously and ends in different time... or what it can be? 看起来像异步运行的命令,并在不同的时间结束......或者它可以是什么?

Simple answer: 简单回答:

how to fix: 怎么修:

ls /usr/bin -lha | tee --output-error=exit-nopipe >(wc -l) >(head) > /dev/null

Details: 细节:

The command head only prints the head of input, so it can finish its job as long as it gets enough input, then exits without waiting for all input. 命令head只打印输入的头部,因此只要输入足够就可以完成其工作,然后退出而不等待所有输入。

So let's replace command head with the simple "head" . 所以让我们用简单的"head"代替命令head

ls /usr/bin -lha | tee >(wc -l) >(read l; echo $l) > /dev/null

The simple "head" will read only one line, then exit, which causes that the pipe file gets closed immediately before tee finishes transferring all data to it. 简单的"head"将只读取一行,然后退出,这会导致管道文件在tee完成将所有数据传输到它之前立即关闭。

So no doubt, you'll get same result with the simple "head" . 所以毫无疑问,你会得到与简单的"head"相同的结果。 wc still prints wrong number. wc仍然打印错误的号码。

The root reason of your issue, I think you can conclude yourself, is that one of the output pipes of tee is closed earlier, tee hits a write error , and then stops writing to other output files. 你认为你问题的根本原因是, tee的输出管道之一先前关闭, tee遇到写入错误 ,然后停止写入其他输出文件。

After understanding the root reason, I think it would be very easy for you to understand the following section in man page. 在理解了根本原因之后,我认为您将很容易理解手册页中的以下部分。

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.

Some extra words 一些额外的话

Actually if you replace >(wc -l) with a regular file in your problematic command line, you will find the file size will always be 16384 or 20480 or 32768 or 36864 or 28672 or ..., all of which are the multiple of 4096. (The writing to the regular file is incomplete because tee aborts earlier. If the writing was complete, the file size would be any value.) 实际上,如果你在有问题的命令行中用常规文件替换>(wc -l) ,你会发现文件大小总是16384或20480或32768或36864或28672或......,所有这些都是4096.(对常规文件的写入不完整,因为tee早先中止。如果写入完成,文件大小将是任何值。)

4096 is the value of PIPE_BUF for most UNIX-like system. 对于大多数类UNIX系统,4096是PIPE_BUF的值。 If you know what PIPE_BUF is, you will easily understand why the file size is always the multiple of 4096. 如果您知道PIPE_BUF是什么,您将很容易理解为什么文件大小始终是4096的倍数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM