我正在尝试将信息传递到一个不接受来自标准输入的输入的程序中。为此,我使用 /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
我的问题是,这两种操作有什么区别,为什么它们会给出不同的结果?作为一个额外的问题,是否有使用“<”符号指定输入的适当术语?
更新:
我目前最好的猜测是正在运行的程序内部的某些东西利用了文件中的查找。下面的答案似乎表明它与文件指针有关,但运行以下小测试程序:
#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
并试图用它来表达它。它可能有效,但也可能无效。