I have a very strange situation while trying to use a specific tool (esearch
from the NCBI E-utilities suite) in a while loop. This is my input file, a list of strings, one per line:
$ cat transcripts.list
NR_169596.1
NR_169595.1
NR_169594.1
I want to run the esearch
command using each of those strings as an argument, so I do:
$ while read -r line; do echo "Line: $line"; esearch -db nucleotide -query "$line"; done < transcripts.list
Line: NR_169596.1
<ENTREZ_DIRECT>
<Db>nucleotide</Db>
<WebEnv>MCID_61bb689d20b59b3e2e2d405d</WebEnv>
<QueryKey>1</QueryKey>
<Count>1</Count>
<Step>1</Step>
</ENTREZ_DIRECT>
This is a single result, not three, as you can see by the single echo
that runs.
The same thing works, however, if I use a bad practice for
loop:
$ for line in $(cat transcripts.list); do echo "Line: $line"; esearch -db nucleotide -query "$line"; done
Line: NR_169596.1
<ENTREZ_DIRECT>
<Db>nucleotide</Db>
<WebEnv>MCID_61bb68cabbe98560233344a7</WebEnv>
<QueryKey>1</QueryKey>
<Count>1</Count>
<Step>1</Step>
</ENTREZ_DIRECT>
Line: NR_169595.1
<ENTREZ_DIRECT>
<Db>nucleotide</Db>
<WebEnv>MCID_61bb68cad05f5825d75e3ace</WebEnv>
<QueryKey>1</QueryKey>
<Count>1</Count>
<Step>1</Step>
</ENTREZ_DIRECT>
Line: NR_169594.1
<ENTREZ_DIRECT>
<Db>nucleotide</Db>
<WebEnv>MCID_61bb68cb6bdec5435b5a41cb</WebEnv>
<QueryKey>1</QueryKey>
<Count>1</Count>
<Step>1</Step>
</ENTREZ_DIRECT>
Question: How is this possible? Even if there is some sort of bug in the specific esearch
program, that shouldn't affect the looping, so why is the shell exiting after the first iteration? And how can the for
work and the while
fail? What do they do differently here?
Some more details.
Adding an
echo
in front of the esearch command makes the loop behave as expected, so this has to be related to the specificesearch
command (but how can that break the shell loop?):$ while read -r line; do echo esearch -db nucleotide -query "$line"; done < transcripts.list esearch -db nucleotide -query NR_169596.1 esearch -db nucleotide -query NR_169595.1 esearch -db nucleotide -query NR_169594.1
There is nothing odd in the list itself, I can reproduce it with different lists and there are no hidden characters:
$ od -c transcripts.list 0000000 N R _ 1 6 9 5 9 6 . 1 \n N R _ 1 0000020 6 9 5 9 5 . 1 \n N R _ 1 6 9 5 9 0000040 4 . 1 \n 0000044
I get the same behavior in bash and dash, so it can't be related to things like PIPEFAIL or anything like that. In any case, the exit status of the command is 0:
while read -r line; do esearch -db nucleotide -query "$line"; echo "EXIT: $?"; done < transcripts.list <ENTREZ_DIRECT> <Db>nucleotide</Db> <WebEnv>MCID_61bb69e71191d1185543b24a</WebEnv> <QueryKey>1</QueryKey> <Count>1</Count> <Step>1</Step> </ENTREZ_DIRECT>
This is happening on a system running Ubuntu, bash, version 4.4.20(1)-release. You can install the
efetch
tool withsudo apt install ncbi-entrez-direct
, if you want to try this out.Works as expected in a loop using a different language. For instance, in
perl
:$ perl -ne 'chomp;system("esearch -db nucleotide -query \"$_\"")' transcripts.list <ENTREZ_DIRECT> <Db>nucleotide</Db> <WebEnv>MCID_61bb6c68d8f66e4bb03f00e8</WebEnv> <QueryKey>1</QueryKey> <Count>1</Count> <Step>1</Step> </ENTREZ_DIRECT> <ENTREZ_DIRECT> <Db>nucleotide</Db> <WebEnv>MCID_61bb6c69947ca95fce4d4f0f</WebEnv> <QueryKey>1</QueryKey> <Count>1</Count> <Step>1</Step> </ENTREZ_DIRECT> <ENTREZ_DIRECT> <Db>nucleotide</Db> <WebEnv>MCID_61bb6c6a85c14642940393f9</WebEnv> <QueryKey>1</QueryKey> <Count>1</Count> <Step>1</Step> </ENTREZ_DIRECT>