ファイル記述子が端末デバイスを指しているかどうかを伝える
プログラムは、isatty()標準のC関数を使用して、ファイル記述子がttyデバイスに関連付けられているかどうかを確認できます(通常はioctl()、fdがttyデバイスを指していないときにエラーを返す無害なtty固有のシステムコールを行います) 。
[/ testユーティリティはでそれを行うことができます-t演算子。
if [ -t 1 ]; then
echo stdout is open to a terminal
fi
GNU / Linuxシステムでのlibc関数呼び出しのトレース:
$ ltrace [ -t 1 ] | cat
[...]
isatty(1) = 0
[...]
システムコールのトレース:
$ strace [ -t 1 ] | cat
[...]
ioctl(1, TCGETS, 0x7fffd9fb3010) = -1 ENOTTY (Inappropriate ioctl for device)
[...]
パイプを指しているかどうかを知る
fdがパイプ/ fifoに関連付けられているかどうかを判断するには、fstat()システムコールを使用st_modeして、そのfdで開かれたファイルのタイプと権限を含むフィールドを持つ構造体を返します。S_ISFIFO()標準Cマクロは、その上で使用できるst_modeFDがFIFO /パイプであるかどうかを決定するフィールド。
を実行できる標準ユーティリティはありませんがfstat()、それを実行statできるコマンドの互換性のない実装がいくつかあります。zshのstat組み込みでstat -sf "$fd" +mode、最初の文字がタイプを表す文字列表現としてモードを返します(pパイプの場合)。GNU statはで同じことを行うことができますstat -c %A - <&"$fd"がstat -c %F - <&"$fd"、型だけを報告する必要もあります。BSDの場合stat:stat -f %St <&"$fd"またはstat -f %HT <&"$fd"。
シーク可能かどうかを伝える
一般に、アプリケーションはstdoutがパイプであるかどうかは気にしません。彼らはそれがシーク可能であることを気にするかもしれません(一般に、バッファリングするかどうかを決定しない)。
fdがシーク可能かどうかをテストするには(パイプ、ソケット、ttyデバイスはシーク不可、通常のファイル、およびほとんどのブロックデバイスは一般にそうです)、相対的な lseek() 0のシステムコール(無害)ます。ddインターフェースである標準ユーティリティですが、オフセット0を要求するlseek()と実装はまったく呼び出さlseek()れないため、そのテストには使用できません。
zshそしてksh93シェルはかかわらず、事業者を募集して組み込みがあります。
$ strace -e lseek ksh -c ': 1>#((CUR))' | cat
lseek(1, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
ksh: 1: not seekable
$ strace -e lseek zsh -c 'zmodload zsh/system; sysseek -w current -u 1 0 || syserror'
lseek(1, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
Illegal seek
バッファリングを無効にする
このscriptコマンドは、擬似端末ペアを使用してプログラムの出力をキャプチャするため、プログラムのstdout(およびstdinとstderr)は擬似端末デバイスになります。
stdoutが端末デバイスに対するものである場合、一般にまだある程度のバッファリングがありますが、それは行ベースです。 printf/ putsおよびcoは、改行文字が出力されるまで何も書き込みません。他の種類のファイルの場合、バッファリングはブロック単位(数キロバイト)です。
ここでQ&Asの数で議論されているバッファリングを無効にするには、いくつかのオプションがあります(を検索バッファー解除またはstdbufは、缶リダイレクトないカット出力は、いくつかのアプローチを与える)ことによって行うことができるよう疑似端末を使用して、どちらかsocat/ script/ expect/ unbuffer(expectスクリプト)/ zshさんzptyまたはGNUの又はFreeBSDのにより行われるようにバッファリングを無効にするために実行可能のコードを注入することによりstdbuf。