I am trying to pass information to a program that does not accept input from stdin. To do this, I use / dev / stdin as an argument, and then try to connect to it. I noticed that if I do this with a pipe symbol:
[ pkerp@comp ernwin]$ cat fess/structures/168d.pdb | MC-Annotate /dev/stdin
I have no conclusion. If, however, I do the same thing using the left carriage character, it works fine:
[ 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
My question is: what is the difference between these two operations and why do they give a different result? As a bonus question, is there a suitable term to indicate input using the '<' character?
Update:
My best guess is that something internal for the program to run uses a file search. The answers below show that this has something to do with file pointers, but the following small test program is running:
#include <stdio.h> int main(int argc, char *argv[]) { FILE *f = fopen(argv[1], "r"); char line[128]; printf("argv[1]: %sf: %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); }
indicates that everything happens the same way until the fseek function is called:
[ 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
Using process substitution suggested by Christopher Neilan causes the program to hang above without even reading the input, which also seems a bit strange.
[ pete@kat tmp]$ ./a.out /dev/stdin <( cat temp ) argv[1]: /dev/stdin f: 3
Looking at the strace output, I confirm my suspicion that a search attempt is being performed, which does not work in the pipe version:
_llseek(3, 0, 0xffffffffffd7c7c0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
And succeed in the redirect version.
_llseek(3, 0, [0], SEEK_CUR) = 0
The moral of the story: do not arbitrarily try to replace the /dev/stdin argument and try to connect to it. It may work, but it is not.