我正在尝试将信息传递给不接受来自stdin的输入的程序.为此,我使用/ dev/stdin作为参数,然后尝试输入我的输入.我注意到如果我用管道字符做这个:
[pkerp@comp ernwin]$ cat fess/structures/168d.pdb | MC-Annotate /dev/stdin
Run Code Online (Sandbox Code Playgroud)
我没有输出.但是,如果我使用左插入符字符做同样的事情,它可以正常工作:
[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
Run Code Online (Sandbox Code Playgroud)
我的问题是,这两项业务之间有什么区别?为什么它们会产生不同的结果呢?作为一个额外的问题,是否有一个使用"<"符号指定输入的正确术语?
更新:
我目前最好的猜测是,正在运行的程序内部的东西会利用文件中的搜索.下面的答案似乎表明它与文件指针有关,但运行以下小测试程序:
#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);
}
Run Code Online (Sandbox Code Playgroud)
表示在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
Run Code Online (Sandbox Code Playgroud)
正如Christopher Neylan建议的那样使用过程替换导致上面的程序挂起而甚至没有读取输入,这看起来也有点奇怪.
[pete@kat tmp]$ ./a.out /dev/stdin <( cat temp )
argv[1]: /dev/stdin f: 3
Run Code Online (Sandbox Code Playgroud)
查看strace输出证实了我怀疑在管道版本中尝试的查找操作失败:
_llseek(3, 0, 0xffffffffffd7c7c0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
Run Code Online (Sandbox Code Playgroud)
并成功进行重定向版本.
_llseek(3, 0, [0], SEEK_CUR) = 0
Run Code Online (Sandbox Code Playgroud)
故事的寓意:不要随意地试图用一个论点来代替它/dev/stdin并尝试用它来管理它.它可能会起作用,但也可能不行.
通过查看有关 MC-Annotate http://bioinfo.cipf.es/ddufour/doku.php?id=mc-annotate的信息 ,管道无法工作的原因是因为 MC-Annotate 无法识别cat文件的输出作为类型之一.pbd
管道将命令连接在一起,第一个命令的输出用作下一个命令的输入。
'<'('小于'、'左箭头'、'左尖括号')将文件输入到命令中。
http://tldp.org/LDP/abs/html/io-redirection.html#IOREDIRECTIONREF2