判斷標準輸出是否指向一個終端

你有沒有留意過下面這種場景:git

$  lsshell

file1 file2 file3 file4 file5小程序

$ ls | cat函數

file1spa

file2ip

file3it

file4io

file5table

單獨執行 ls 時,它的輸出是一行多個文件名,在它後面接個管道的話,它的輸出就變成了一行一個文件名,這是爲何呢?這種表現的原理是:ls 程序自身能夠判斷出(經過 isatty() 庫函數)它的標準輸出是指向了一個終端,仍是別的什麼地方(管道或者普通文件)。若是是前者,則按一行多個文件名輸出,不然按一行一個輸出。class

咱們能夠本身寫個簡單的 c 程序演示一下:

$  cat foo.c

#include <stdio.h>

int main() {

    printf(isatty(1) ? "終端\n" : "非終端\n");

}

$ gcc foo.c -o foo

$ ./foo

終端

$ ./foo | cat

非終端

$ ./foo > file

$ cat file

非終端

然而恰恰有時候,在咱們想要把一個命令的標準輸出保存起來或者交給其它命令繼續處理的時候,遇到了上面這種狀況。好比 git log 命令,git log 直接在終端上執行是有顏色的,git log > git.log; cat git.log; 就沒有顏色了。這個時候咱們須要用到 script 命令,再用上面本身寫的小程序演示一下好了:

$ ./foo | cat

非終端

$ script -qc ./foo | cat

終端

script 命令能夠騙過 foo 命令,讓它覺得本身的標準輸出是個終端。script 命令的 -c 選項就是專門幹這個的:

-c COMMAND
Run the COMMAND rather than an interactive shell. This makes it easy for a script to capture the output of a program that behaves differently when its stdout is not a tty.

在 Bash 中,也有相似 c 語言中 isatty 函數功能的東西,就是 -t fd 條件表達式:

$ cat foo.sh

if [[ -t 1 ]];then echo 終端;else echo 非終端;fi

$ ./foo.sh

終端

$ ./foo.sh | cat

非終端

$ script -qc ./foo.sh | cat

終端

相關文章
相關標籤/搜索