Você pode colocar redirecionamentos em qualquer posição em um comando simples (ou seja, invocar um apelido, função, embutido ou executável com parâmetros). Por outro lado, se você quiser aplicar um redirecionamento a comandos compostos, os redirecionamentos devem vir depois. É assim que a sintaxe do shell é projetada. Por exemplo, os seguintes são equivalentes:
<myinput mycommand argument
mycommand <myinput argument
mycommand argument <myinput
Considerando que o redirecionamento não pode ser movido em
while …; do …; done <myinput
{ command1; command2; } <myinput
Você só pode aplicar um redirecionamento a um comando composto se ele terminar com uma palavra-chave ou com pontuação. Para aplicar o redirecionamento a algo como foo && bar
ou foo; bar
ou foo | bar
, coloque o comando entre chaves, por exemplo,
{ foo && bar; } <myinput
Os scripts
while read a; do
echo "$a"
done <myfile
e
while read a <myfile; do
echo "$a"
done
são ambos sintaticamente corretos, mas o segundo não faz nada útil. Um operador de redirecionamento em um comando significa:
- Abra o arquivo especificado.
- Anexe o arquivo especificado ao descritor de arquivo de requisitos (por exemplo, 0 para
<
). - Execute o comando.
- Feche o descritor de arquivos.
Portanto, read a <myfile
abre o arquivo novamente em cada iteração, o que significa que ele continua lendo a primeira linha para sempre.
Se você quiser usar um loop de leitura de tempo e quiser manter a entrada padrão circundante para o corpo do loop, leia um descritor de arquivo diferente.
while read a <&3; do
# commands that can use stdin
done 3<myfile
O operador de redirecionamento <&3
simplesmente faz a duplicação do descritor de arquivo, ele não “abre o arquivo novamente” - na enumeração acima, não há etapa 1.