在创建 bash 脚本时,我发现这段代码ls
将所有文件放在一行:
pi@raspberrypi:~/ptlrestinterface$ ls
update.sh web.config MyApp.runtimeconfig.json
仍然ls | head -n1
只打印第一个文件:
pi@raspberrypi:~/ptlrestinterface$ ls | head -n1
update.sh
我希望它输出整行,而不是第一个文件。
在通过管道输出时hexdump
,我看到ls
总是在每个条目后输出一个0a
,但是在控制台上,它将它们放置在彼此旁边。
显然ls
对控制台(或 的控制台ls
)有一些了解。这是如何工作的?我在哪里可以找到有关此行为的文档?
isatty()
它在其文件描述符上调用libc 函数stdout
来确定输出是否发送到终端。在内部,
isatty()
尝试使用ioctl()
特定于 tty 设备的调用之一 - 最有可能ioctl(TCGETS)
(检索命令显示的通用 tty 设置stty
);如果成功,则该文件是一个 tty 设备。这会影响 ls 默认情况下是否会对其输出进行列化,默认情况下是否会使用颜色,以及其他一些事情,例如是否会引用文件名。
如果
stdout
确实是一个终端,则ls
使用另一个特定于 tty 的ioctl(TIOCGWINSZ)
来检索其尺寸(在现代系统上已由终端仿真器存储在那里)以找出它可以容纳多少列。该stty size
命令还获取这些;尝试在strace
.全屏程序还会对
SIGWINCH
每次终端仿真器更新 tty 尺寸时内核发送的信号做出反应,以表明它们需要以新尺寸重新绘制所有内容。对于不太技术性的解释,请观察尝试这两个命令时会发生什么:
管道传输
cat
“不执行任何操作”,只是ls
“注意到”它的输出正在通过管道传输到某个地方。因此它会相应地改变其行为。一旦你理解了
ls
输出的内容,当它通过 时会发生什么就很简单了head -n1
。