A mudança é para este pedaço
while read name; do
efetch -db nucleotide -id $name -format gpc > $name.xml;
done < "$@"
que torna o efetch
no loop executado com sua entrada padrão redirecionada para o arquivo fornecido pelos argumentos. Então, isso faz duas alterações na maneira como o efetch
é usado:
- sua entrada padrão não é mais o padrão (terminal)
- sua lista de parâmetros não é mais literalmente os parâmetros da linha de comando para o script, mas indiretamente, de um arquivo.
Se efetch
detectar que sua entrada não é um terminal, ela poderá reabrir o terminal diretamente (talvez seja a isso que você está se referindo como "efetch aceita stdin em vez de um id"). Alternativamente, se efetch
estiver lendo seu stdin, ele poderá ler algo inesperado (em um teste rápido, esse parece ser o próprio script).
@chepner apontou que o shell (bash neste caso) não gera um subprocesso para o loop . Eu tinha em mente um caso diferente que faz. Considere estes dois scripts:
#!/bin/bash
LAST=...
while read name
do
/bin/echo "** $name"
LAST="$name"
done < "$@"
echo "...$LAST"
e
#!/bin/bash
LAST=...
cat "$@" | while read name
do
/bin/echo "** $name"
LAST="$name"
done
echo "...$LAST"
O último (pipe) irá ecoar "......" no final, enquanto o antigo (redirecionamento) ecoa a última variável atribuída a LAST
dentro do loop. O formulário que usa um pipe às vezes é comentado exigindo que um subprocesso seja responsável pelo motivo pelo qual as atribuições de variáveis não são propagadas fora do loop.
Curiosamente, existem diferenças entre os shells para o último (um pipe) em relação ao número de processos utilizados. Testando com (Debian / testing) bash, traço (/ bin / sh), zsh e ksh93, usando strace -fo
para capturar chamadas de sistema e IDs de processo:
#!/bin/sh
for sh in bash dash zsh ksh93
do
echo "++ $sh"
strace -fo $sh.log ./do-$sh ./once
LC=$(sed -e 's/ .*//' $sh.log |sort -u |wc -l)
WC=$(wc -l $sh.log)
echo "-- $LC / $WC"
done
O script mostra o número de processos e o número de chamadas do sistema para cada shell. (O arquivo once
contém duas linhas: "first" e "second", para eliminar um limite de teste).
Eu vejo que o zsh e o ksh93 usam um processo a menos que o bash e o dash:
$ ./testit
++ bash
** first
** second
......
-- 5 / 401 bash.log
++ dash
** first
** second
......
-- 5 / 222 dash.log
++ zsh
** first
** second
...second
-- 4 / 568 zsh.log
++ ksh93
** first
** second
...second
-- 4 / 336 ksh93.log
A execução do pipe requer mais 1 ou 2 processos do que usar um documento here para este exemplo.