ls
返回多列中的输出,而返回与我尝试过的目录ls|cat
相同的字节输出。ls -1
我仍然看到ls -1
答案,比如ls -1|wc -l
。有理由选择吗ls -1
?为什么会...|cat
改变 的输出ls
?
答案1
ls
测试输出是否发送到终端。如果输出不发送到终端,则为-1
默认输出。 (这可以被-C
、-m
、 或选项之一覆盖-x
。)
因此,当ls
在管道中使用 且您没有使用其他选项覆盖它时,ls
将使用-1
. 您可以信赖此行为,因为 POSIX 需要此行为
POSIX 规范
当输出不发送到终端时, POSIX 要求-1
默认:
默认格式应为每行列出一个条目到标准输出;终端或指定 -C、-m 或 -x 选项之一时除外。如果输出到终端,则格式是实现定义的。
覆盖默认单列格式的三个选项是:
-C
写入多文本列输出,其中条目根据整理顺序按列排序。文本列的数量和列分隔符字符未指定,但应适应输出设备的性质。此选项禁用长格式输出。-m
流输出格式;列出页面上的路径名,由 <comma> 字符后跟 <space> 字符分隔。当行上没有空间容纳下一个列表条目时,请在分隔符序列之后使用 <newline> 字符作为列表终止符。此选项禁用长格式输出。-x
与 -C 相同,不同之处在于多文本列输出是通过跨列而不是向下排序的条目生成的。此选项禁用长格式输出。
GNU 文档
'-1'
'--format=single-column'
每行列出一个文件。当标准输出不是终端时,这是 ls 的默认设置。另请参见 -b 和 -q 选项以禁止在文件名中直接输出换行符。 [强调已添加]
例子
让我们创建三个文件:
$ touch file{1..3}
当输出到达终端时,GNUls
选择使用多列格式:
$ ls
file1 file2 file3
当输出进入管道时,POSIX 规范要求默认为单列:
$ ls | cat
file1
file2
file3
覆盖默认单列行为的三个例外是-m
逗号分隔、-C
向下排序的列和-x
跨列排序的:
$ ls -m | cat
file1, file2, file3
$ ls -C | cat
file1 file2 file3
$ ls -x | cat
file1 file2 file3
答案2
为什么通过管道传输标准输出会改变 的行为
ls
?因为它就是这样设计的。这POSIX 规范说:默认格式应为每行列出一个条目到标准输出;例外情况是终端或当其中之一
-C
,-m
, 或者-x
选项已指定。如果输出到终端,则格式是实现定义的。-l
这实际上对于输出到终端的默认行为(当没有由像or 之类的选项指定时-1
)不明确,并且GNU Coreutils 文档说如果标准输出是终端,则输出按列排列(垂直排序),控制字符输出为问号;否则,每行列出一个输出,并按原样输出控制字符。
因此,您可以看到输出到文件的行为与输出到管道的行为相同;也就是说,每行一个条目,就像
-1
已指定一样。- 为什么要这样设计?可能无法确定(除非有人能找到一些设计说明),但我猜:
- 当
ls
写入终端时,它期望人类正在查看输出。人们更喜欢以最少的必要行数获取信息,因此内容不会在屏幕上滚动。 - 当
ls
写入管道时,它期望另一个程序正在读取输出。对于程序来说,读取每行一个值的数据比尝试解析列要容易得多(因为文件名可以包含空格)。
- 当
ls -1
当您写入文件或管道时,是否有理由选择它?不。
答案3
当管道 ls 时,ls 无法确定控制台实际有多少列(与右侧命令无关)。所以 ls 只是根据自己的选择这样做,或者换句话说,这种行为是不稳定并可能在未来版本中发生变化。
相比之下,ls -1
它是为了一般计数或脚本编写的目的而创建的,因此它的行为是稳定的。