了解输出到 stdout 和常规文件的区别
Understanding the difference over output to stdout and a regular file
这是 ls
命令的输出:
$ ls
addr.sh hello.txt test.sh xxx.txt
这里我们有相同的命令重定向到 stderr:
$ ls 1>&2
addr.sh hello.txt test.sh xxx.txt
产生几乎相同的输出。
然而,重定向到常规文件会导致 ls
产生多行输出:
$ ls > xxx.txt
$ cat xxx.txt
addr.sh
hello.txt
test.sh
xxx.txt
为什么以及幕后发生了什么?
Why
因为有人这样编程。
what is happening
您的 ls
实现检查标准输出是否连接到终端设备。如果是,它会输出一个漂亮的打印输出,以类似列的方式用空格分隔。如果输出不是终端设备,它会输出一个换行符分隔的列表。*
检查文件描述符是否在终端上打开可以使用内部调用 isatty()
C 函数的 test -t FD
命令完成。
ls
基本上是这样的:
{ if [ -t 1 ]; then ls -C; else ls -1; fi }
# From man ls:
# -C list entries by columns
# -1 list one file per line.
当输出不是终端设备时,许多实用程序会改变它们的行为。
*请注意,当输出不是终端 The default format shall be to list one entry per line to standard output; the exceptions are to terminals [...]
.
时,POSIX ls specification 强制输出为每个文件一个条目的列表
behind the scenes?
我假设您有 coreutils ls
实现。在 coreutils/ls.c#L1886 程序只检查是否 isatty(STDOUT_FILENO)
并根据它设置引用样式和类似列或类似换行符的输出。
这是 ls
命令的输出:
$ ls
addr.sh hello.txt test.sh xxx.txt
这里我们有相同的命令重定向到 stderr:
$ ls 1>&2
addr.sh hello.txt test.sh xxx.txt
产生几乎相同的输出。
然而,重定向到常规文件会导致 ls
产生多行输出:
$ ls > xxx.txt
$ cat xxx.txt
addr.sh
hello.txt
test.sh
xxx.txt
为什么以及幕后发生了什么?
Why
因为有人这样编程。
what is happening
您的 ls
实现检查标准输出是否连接到终端设备。如果是,它会输出一个漂亮的打印输出,以类似列的方式用空格分隔。如果输出不是终端设备,它会输出一个换行符分隔的列表。*
检查文件描述符是否在终端上打开可以使用内部调用 isatty()
C 函数的 test -t FD
命令完成。
ls
基本上是这样的:
{ if [ -t 1 ]; then ls -C; else ls -1; fi }
# From man ls:
# -C list entries by columns
# -1 list one file per line.
当输出不是终端设备时,许多实用程序会改变它们的行为。
*请注意,当输出不是终端 The default format shall be to list one entry per line to standard output; the exceptions are to terminals [...]
.
behind the scenes?
我假设您有 coreutils ls
实现。在 coreutils/ls.c#L1886 程序只检查是否 isatty(STDOUT_FILENO)
并根据它设置引用样式和类似列或类似换行符的输出。