这与bash无关。它只是反映了C标准库I/O函数缓冲输出的方式。
下面是Linux系统中man setvbuf
的一个有用摘录(解释主要来自C和Posix标准,但我认为在这个摘录中很容易找到和理解)。第二段是你看到的行为的解释。
可用的三种缓冲类型是无缓冲,块缓冲和行缓冲。当输出流没有缓冲时,信息一出现就显示在目标文件或终端上;当它被块缓冲时,许多字符被保存并写成一个块;当行缓冲字符被保存直到输出换行符或从连接到终端设备(通常为stdin)的任何流读取输入时。 fflush(3)函数可以用来尽早强制阻止。 (见fclose(3)。)
通常所有文件都是块缓冲的。如果一个流引用了一个终端(正如标准输出通常那样),它是行缓冲的。标准错误流stderr默认情况下始终未缓冲。
因此,回顾一下。 stdout
通常指的是终端,因此是行缓冲的,但是您已将其重定向到一个文件,因此它被块缓冲。但是,stderr
始终是无缓冲的,无论它是否被重定向。
因此,任何打印到stderr
的东西都会立即出现,而打印到stdout
的任何内容都将保留到缓冲区填满(在Linux上通常为8kb)。
请注意,当ls
检测到stdout
不是终端时,它会默认设置-1
标志(每行一个文件名)。否则,它会默认设置-x
标志(尽可能多的文件名以适合一行)。这意味着您将在终端上看到相同的反转,而无需任何重定向:
$ ls good bad
ls: cannot access bad: No such file or directory
good