ls是否与ls -1相同?


19

ls返回几列的输出,而ls|cat返回与ls -1我尝试过的目录相同的字节输出。我仍然看到ls -1答案中的管道,例如ls -1|wc -l。有没有理由更喜欢ls -1?为什么...|cat更改输出ls


1
文件名可以包含换行符,因此您可以将它们数几次……您可以适当地这样做:( n=0; for i in .* *; do ((n++)) ; done ; echo $n如果不想计数,请删除。*)。或:(ls -1d ./.* ./* | grep '^\./' | wc -l 文件名不能包含“ /”)
Olivier Dulac

3
ls默认情况下,输出到终端的颜色通常包括颜色代码。为了输出到非终端,通常默认情况下禁用颜色。在GNU中,这就是--color={always,auto,never}IIRC。如果一种颜色包含但另一种颜色不包含在内,则输出在屏幕上可能看起来完全相同,但它们不是字节相同的(颜色代码构成ls输出的一部分)。
CVn

@MichaelKjörling我认为您应该将其写为答案。
200_success

@MichaelKjörling我没有考虑过这很有趣。有没有一种通用的方法可以始终将管道好像输出到终端一样,而不必记住颜色和列输出等的终端选项?
rubystallion

@rubystallion听起来像是一个很好的独立问题。
CVn

Answers:


26

ls测试输出是否将发送到终端。如果输出不发送到终端,-1则为默认值。(这可以通过的一个被覆盖-C-m-x选项)。

因此,当ls在管道中使用时,并且尚未用其他选项覆盖它时,ls将使用-1您可以依靠它,因为POSIX要求此行为

POSIX规格

-1每当输出不发送到终端时,POSIX都将其作为默认值:

POSIX规范

默认格式是在标准输出中每行列出一个条目。终端或指定了-C,-m或-x选项之一的情况除外。如果输出到终端,则格式是实现定义的。

这三个覆盖默认单列格式的选项是:

-C
根据排序顺序,写出多文本列输出,并按列对条目进行排序。文本列的数量和列分隔符未指定,但应根据输出设备的性质进行调整。此选项禁用长格式输出。

-m
流输出格式;列出页面中的路径名,用<逗号>字符和<space>字符分隔。当下一行列表中没有足够的空间时,请使用<newline>字符作为列表终止符,并在分隔符序列之后。此选项禁用长格式输出。

-x
与-C相同,不同之处在于,多文本列输出的产生是通过跨列而不是按列对条目进行排序的。此选项禁用长格式输出。

GNU文档

GNU ls手册

'-1'
'--format = single-column'
每行列出一个文件。当标准输出不是终端时,这是ls的默认值。另请参见-b和-q选项,以禁止在文件名中直接输出换行符。[强调已添加]

例子

让我们创建三个文件:

$ touch file{1..3}

当输出到达终端时,GNU ls选择使用多列格式:

$ 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

“当输出到终端时,POSIX要求默认为-1:” ... ...但是引号表明,除了当输出到终端(或其他条件)时,它均要求-1为默认值
muru

@muru感谢您抓住这一点!答案已更新。
John1024 '17

好吧,每一朵云都有一线希望。因为您的答案在我的发布之前已被接受,所以我得到了一个时髦的披萨帽子!
G-Man说'Resstate Monica''De​​c

@ G-Man很好。而且,它是一顶英俊的帽子!
John1024 '17

9
  • 为什么用管道输送标准输出会改变行为ls?因为它是按这种方式设计的。该POSIX规范说:

    默认格式是在标准输出中每行列出一个条目。例外是,给终端时,或者当所述一个-C-m或者-x被指定的选项。如果输出到终端,则格式是实现定义的。

    对于输出到终端的默认行为(当未由诸如-l或的选项指定时)实际上是模棱两可的-1GNU Coreutils文档

    如果标准输出是终端,则输出为列(垂直排列),并且控制字符作为问号输出;否则,输出每行列出一个,并且控制字符按原样输出。

    因此,您可以看到输出到文件的行为与输出到管道的行为相同;也就是说,每行一个条目,就好像-1已经指定了一样。

  • 为什么这样设计?可能无法确切知道(除非有人可以找到一些设计说明),但是我想:
    • ls写终端时,它期望一个人正在看输出。人们会希望以最少的行数获取信息,因此东西不会在屏幕上滚动。
    • ls写入管道时,它期望另一个程序正在读取输出。对于程序而言,读取每行一个值的数据比必须尝试解析列要容易得多(因为文件名可以包含空格)。
  • ls -1 在写入文件或管道时,是否有理由更喜欢?没有。

-4

使用ls进行管道传输时,ls无法确定控制台实际具有的列数(独立于右侧命令)。因此,ls仅根据自己的选择执行此操作,换句话说,此行为是不稳定的,并且在以后的版本中可能会更改。

相反,ls -1通常是出于计数或编写脚本的目的而创建的,因此其行为是稳定的。


9
正如其他答案所说的那样,POSIX要求此行为,因此将其称为不稳定是错误的。
亨里克-停止伤害莫妮卡
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.