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)
您的发现突出了解析 的输出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标志并注意到输出已停止,但您的脚本仍会卡住。