ls 的输出有换行符,但显示在一行上。为什么?

the*_*wer 65 ls bash terminal od

我想我可能忽略了关于 shell 的一个相对基本的观点。默认情况下,ls命令的输出用换行符分隔输出,但 shell 将输出显示在一行上。

任何人都可以向我解释这一点吗?我一直假设输出只是由空格分隔,但现在我看到输出由换行符分隔,我希望输出显示在单独的行上。

例子:

cpoweradm@debian:~/lpi103-4$ ls text*
text1  text2  text3
Run Code Online (Sandbox Code Playgroud)

od显示输出由换行符分隔:

cpoweradm@debian:~/lpi103-4$ ls text* | od -c
0000000   t   e   x   t   1  \n   t   e   x   t   2  \n   t   e   x   t
0000020   3  \n
0000022
Run Code Online (Sandbox Code Playgroud)

如果存在换行符,那么为什么输出不显示为:

text1 
text2
text3
Run Code Online (Sandbox Code Playgroud)

Mik*_*kel 75

当您通过管道输出输出时,ls行为会有所不同。

这个事实隐藏在信息文档中

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

为了证明这一点,请尝试运行

ls
Run Code Online (Sandbox Code Playgroud)

进而

ls | less
Run Code Online (Sandbox Code Playgroud)

这意味着,如果您希望保证输出为每行一个文件,无论它是通过管道传输还是重定向,您都必须运行

ls -1
Run Code Online (Sandbox Code Playgroud)

-1是第一)

或者,您可以ls | less通过运行强制按列输出

ls -C
Run Code Online (Sandbox Code Playgroud)

(-C是大写C)

  • @theconnorpower:它非常特定于`ls`。它很有用,但显然不一致且令人惊讶。但请注意,一些产生彩色输出的命令也会在通过管道传输时去除颜色。 (7认同)
  • @theconnorpower:琐事:Unix 的发明者继续编写 Plan9。在 Plan9 中,`ls` 总是每行打印一个,而 `lc` 总是按列打印。 (7认同)
  • @theconnorpower:还有一些程序可以读取终端的大小,并相应地调整它们的输出,例如在 Debian 上`dpkg -l` 将使用整个屏幕宽度,但如果它打印到管道,它假定终端是 80 列宽,并在必要时缩写输出以使其适合。 (2认同)
  • 程序如何确定其输出是重定向到文件还是转到 shell? (2认同)

Cal*_*leb 8

您的发现突出了解析 的输出ls始终是一个坏主意的主要原因。有关完整说明,请参阅 Greg 的 wiki 。

反过来想想你的问题。您注意到 ls 有时会,有时不会在输出之间打印换行符。对于在脚本中使用或由-1标志强制使用时,它确实如此。每个文件末尾有一个换行符。什么也不能保证每一个新行代表一个新的文件名。实际上,如果文件名本身包含换行符,则 ls 的输出将绝对无法解析。考虑这些文件名:

file1
file2\nfile3
file4
Run Code Online (Sandbox Code Playgroud)

当您创建ls -1一个包含该目录的目录时,您会得到如下所示的内容:

file1
file2
file3
file4
Run Code Online (Sandbox Code Playgroud)

你不会自然地假设有四个文件吗?任何解析 ls 输出的脚本也是如此。实际上有三个文件,其中一个的名称很棘手,但是您无法从 ls.* 的输出中找出来

* 除非您正在使用该-l标志并注意到输出已停止,但您的脚本仍会卡住。

  • 如果你*真的*必须解析`ls`的输出,`-b`选项可以提供帮助。它将换行符转换为 `\n` 等。 (4认同)