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

Mât*_*man 12 command-line ls io-redirection tty

命令如何ls知道它的标准输出是什么?

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

ls /home/matt/tmp 
Run Code Online (Sandbox Code Playgroud)

结果是:

a.txt b.txt c.txt
Run Code Online (Sandbox Code Playgroud)

但是,如果我这样做

ls /home/matt/tmp | cat
Run Code Online (Sandbox Code Playgroud)

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

a.txt
b.txt
c.txt
Run Code Online (Sandbox Code Playgroud)

该进程为标准输出传递了一个文件描述符 1 对吗?它如何确定如何格式化结果?文件描述符是否显示信息?

Sté*_*nez 22

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

int isatty(int fd);
Run Code Online (Sandbox Code Playgroud)

描述
该isatty()函数测试是否fd是指向终端的打开文件描述符


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

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

(many_per_line应该是自我描述的。)


man*_*ork 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
Run Code Online (Sandbox Code Playgroud)


Kus*_*nda 6

从 OpenBSDls(1) 手册:

默认情况下, ls 每行列出一个条目到标准输出;例外情况是终端或指定了 -C、-m 或 -x 选项时。

然后,后来:

-1(数字“一”。)强制输出为每行一个条目。这是不输出到终端时的默认设置。

[...]

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