ls命令的操作方式因收件人而异


12

像这样的命令如何ls知道其标准输出是什么?

ls根据目标标准输出的不同,操作似乎有所不同。例如,如果我这样做:

ls /home/matt/tmp 

结果是:

a.txt b.txt c.txt

但是如果我这样做

ls /home/matt/tmp | cat

结果是(即每个结果换行):

a.txt
b.txt
c.txt

进程被传递了一个文件描述符1,用于stdout吗?如何确定结果的格式?文件描述符是否显示信息?


相关unix.stackexchange.com/q/157285/4671unix.stackexchange.com/q/63108/4671和可能其他人。这似乎是一个热门话题。这可能是其中之一的欺骗。
Faheem Mitha 2015年

Answers:


22

ls程序用于isatty()了解fd 1是tty还是其他(管道,文件等)。来自man 3 isatty

int isatty(int fd);

说明
isatty()功能检查是否fd是一个打开文件描述符指的是终端


更新:ls.c来自coreutils(git修订版43a987e1)的1538行:

  if (isatty (STDOUT_FILENO))
    {
      format = many_per_line;
      /* See description of qmark_funny_chars, above.  */
      qmark_funny_chars = true;
    }

many_per_line应该是自我描述的。)


8

不是确切的答案,而是一个例子。在bash脚本也可以达到类似的效果test/ [[-t

-t FD True if FD is opened on a terminal.

像这样使用它:

bash-4.2$ where() { [[ -t 1 ]] && echo 'my output goes to TTY' || echo 'my output is redirected'; }

bash-4.2$ where
my output goes to TTY

bash-4.2$ where | cat
my output is redirected

bash-4.2$ where > test.file
bash-4.2$ cat test.file
my output is redirected

6

从OpenBSD ls(1) 手册

缺省情况下,ls将每行列出一个条目到标准输出。终端或指定了-C,-m或-x选项的情况除外。

然后,稍后:

-1(数字``one''。)强制输出为每行一个条目。当不输出到终端时,这是默认设置。

[...]

-C强制多列输出;这是输出到终端时的默认设置。


1

您可以ls使用该script 命令在伪终端中执行,将输出的内容ls通过管道传递给另一个命令,并获得与stdout流中没有此类管道的输出格式相同的输出格式,即好像stdout是终端(tty)。

对于底层isatty()已经斯特凡希门尼斯指出,机制看ls.c

ls -G /
ls -G / | cat
script -q /dev/null ls -G / | sed $'s/\r$//g' | cat

# tty | cat
# script -q /dev/null tty | cat
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.