このようなコマンドは、標準出力がls
何であるかをどうやって知ることができますか?
ls
ターゲット標準出力によって動作が異なるようです。たとえば、これを行うと:
ls /home/matt/tmp
結果:
a.txt b.txt c.txt
しかし、もし私がそうするなら
ls /home/matt/tmp | cat
結果は次のとおりです(つまり、各結果は新しい行を置き換えます)。
a.txt
b.txt
c.txt
プロセスには、stdoutのファイル記述子1が渡されます。そうですか?結果の書式設定方法はどのように決定されますか?ファイル記述子は情報を漏洩していますか?
答え1
このプログラムは、fd 1がttyか他のもの(パイプ、ファイルなど...)であるかを判断するls
ために使用されます。isatty()
からman 3 isatty
:
int isatty(int fd);
説明
このisatty()
関数は、fd
開かれたファイル記述子が端末を参照するかどうかをテストします。
修正する:coreutilsの行1538 ls.c
(gitリビジョン43a987e1):
if (isatty (STDOUT_FILENO))
{
format = many_per_line;
/* See description of qmark_funny_chars, above. */
qmark_funny_chars = true;
}
(many_per_line
自己説明が必要です。)
答え2
正確な答えではありませんが、例です。 Bashスクリプトでは、test
/ achievを使用して同様の[[
効果を得ることができます-t
。
-t FD True if FD is opened on a terminal.
次のように使用してください。
bash-4.2$ where() { [[ -t 1 ]] && echo 'my output goes to TTY' || echo 'my output is redirected'; }
bash-4.2$ where
my output goes to TTY
bash-4.2$ where | cat
my output is redirected
bash-4.2$ where > test.file
bash-4.2$ cat test.file
my output is redirected
答え3
OpenBSDからls(1)
手動:
デフォルトでは、ls は、端末または -C、-m、または -x オプションが指定されている場合を除き、標準出力に 1 行に 1 つの項目をリストします。
それから後で:
-1(数字「1」。)出力は1行に1つの項目に強制されます。出力が端末に進まないときのデフォルト値です。
[...]
-C は複数列出力を強制します。これは端末に出力するときのデフォルト値です。
答え4
このコマンドを使用して擬似ls
端末で実行しscript
、他のコマンドの出力をパイプし、そうしls
た stdout ストリームパイプがないかのように、つまり stdout が端末 (tty) のように同じ出力形式を得ることができます。
isatty()
Stéphane Gimenezがすでに指摘している基本的なメカニズムについては、以下を参照してください。ls.c。
ls -G /
ls -G / | cat
script -q /dev/null ls -G / | sed $'s/\r$//g' | cat
# tty | cat
# script -q /dev/null tty | cat