文章出處

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

$  ls

file1 file2 file3 file4 file5

$ ls | cat

file1

file2

file3

file4

file5

單獨執行 ls 時,它的輸出是一行多個文件名,在它后面接個管道的話,它的輸出就變成了一行一個文件名,這是為什么呢?這種表現的原理是:ls 程序自身可以判斷出(通過 isatty() 庫函數)它的標準輸出是指向了一個終端,還是別的什么地方(管道或者普通文件)。如果是前者,則按一行多個文件名輸出,否則按一行一個輸出。

我們可以自己寫個簡單的 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

終端


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()