stdin からの入力を受け付けないプログラムに情報を渡そうとしています。これを行うために、/dev/stdin を引数として使用し、入力をパイプしようとしています。パイプ文字でこれを行うと、次のことに気付きました。
[pkerp@comp ernwin]$ cat fess/structures/168d.pdb | MC-Annotate /dev/stdin
出力がありません。ただし、左キャレット文字を使用して同じことを行うと、問題なく動作します。
[pkerp@plastilin ernwin]$ MC-Annotate /dev/stdin < fess/structures/168d.pdb
Residue conformations -------------------------------------------
A1 : G C3p_endo anti
A2 : C C3p_endo anti
A3 : G C3p_endo anti
私の質問は、これら 2 つの操作の違いは何ですか?なぜ異なる結果が得られるのでしょうか? おまけの質問として、「<」記号を使用して入力を指定するための適切な用語はありますか?
アップデート:
私の現在の最善の推測は、実行中のプログラムの内部にある何かがファイル内のシークを利用しているということです。以下の回答は、ファイルポインタと関係があるが、次の小さなテストプログラムを実行していることを示唆しているようです:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *f = fopen(argv[1], "r");
char line[128];
printf("argv[1]: %s f: %d\n", argv[1], fileno(f));
while (fgets(line, sizeof(line), f)) {
printf("line: %s\n", line);
}
printf("rewinding\n");
fseek(f, 0, SEEK_SET);
while (fgets(line, sizeof(line), f)) {
printf("line: %s\n", line);
}
fclose(f);
}
fseek
関数呼び出しまですべてが同じように発生することを示します。
[pete@kat tmp]$ cat temp | ./a.out /dev/stdin
argv[1]: /dev/stdin f: 3
line: abcd
rewinding
===================
[pete@kat tmp]$ ./a.out /dev/stdin < temp
argv[1]: /dev/stdin f: 3
line: abcd
rewinding
line: abcd
Christopher Neylan が提案したようにプロセス置換を使用すると、入力を読み取らずに上記のプログラムがハングすることにつながりますが、これも少し奇妙に思えます。
[pete@kat tmp]$ ./a.out /dev/stdin <( cat temp )
argv[1]: /dev/stdin f: 3
strace の出力を見ると、パイプ バージョンで失敗するシーク操作が試行されているという私の疑いが確認されます。
_llseek(3, 0, 0xffffffffffd7c7c0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
そしてリダイレクト版で成功。
_llseek(3, 0, [0], SEEK_CUR) = 0
話の教訓: でたらめに引数を置き換えて、/dev/stdin
それにパイプしようとしないでください。うまくいくかもしれませんが、うまくいかないかもしれません。