O redirecionamento de entrada (como em cat < file ) significa que o shell está abrindo o arquivo de entrada e gravando seu conteúdo na entrada padrão de outro processo. Passar o arquivo como um argumento (como acontece ao executar cat file ) significa que o programa que você está usando (por exemplo, cat ) precisa abrir o próprio arquivo e ler o conteúdo.
Basicamente, command file passa um arquivo para command enquanto command < file passa o conteúdo de um arquivo para command . Sim, em casos como cat file vs cat < file não há diferença facilmente percebida no resultado, mas os dois funcionam de maneiras diferentes.
Para entender a diferença, pense em uma criança pequena e um adulto. Ambos podem beber água. No entanto, o adulto pode abrir a torneira e encher um copo (abrir o arquivo e ler seu conteúdo) enquanto a criança precisa que a água seja fornecida diretamente (não é possível abrir o arquivo e só pode processar seu conteúdo). / p>
Alguns programas, como o cat , são capazes de pegar um nome do arquivo como entrada e então abrir o arquivo e fazer o que quiserem nele. É por isso que cat file funciona. Outros programas, no entanto, não têm nenhum conhecimento sobre quais arquivos são ou como usá-los. Tudo o que eles sabem é fluxos de entrada (como o conteúdo do arquivo). Por exemplo, tr :
$ cat file
foo
$ cat file | tr 'o' 'b' ## tr can read a stream
fbb
$ tr 'o' 'b' file ## tr can't deal with files
tr: extra operand ‘file’
Try 'tr --help' for more information.
$ tr 'o' 'b' < file ## input redirection!
fbb
Outro exemplo é ls , que pode lidar com os arquivos muito bem, mas ignora os fluxos de entrada:
$ ls
file1 file2
$ ls file1 ## lists only file1: ls takes file names as arguments
file1
$ ls < file1 ## ls ignores its standard input, this is the same as ls alone
file1 file2
Outros programas não podem lidar com fluxos e, em vez disso, exigem arquivos:
$ rm < file ## fails, rm needs a file
rm: missing operand
Try 'rm --help' for more information.
$ rm file ## works, file is deleted
Alguns programas podem lidar com arquivos de abertura e leitura de fluxos de entrada, mas comportam-se de maneiras diferentes em cada um deles. Por exemplo, wc que, quando recebe um arquivo para abrir, imprime o nome do arquivo, bem como o número de linhas, palavras e caracteres:
$ wc file
1 1 4 file
Mas, se dermos apenas um fluxo, não há como saber que isso vem de um arquivo específico, portanto, nenhum nome de arquivo é impresso:
$ wc < file
1 1 4
O comando md5sum se comporta de maneira semelhante:
$ md5sum file
17fd54512c91e3cd0f70fbaaa9a94d0d file
$ md5sum < file
17fd54512c91e3cd0f70fbaaa9a94d0d -
Note que no primeiro caso o nome do arquivo file é mostrado enquanto, no segundo, "nome do arquivo" é - : entrada padrão.
Agora, se você quiser mais detalhes, você pode usar strace para ver exatamente o que está acontecendo:
strace -e trace=open,close,read,write wc file 2>strace1.txt
e
strace -e trace=open,close,read,write wc < file 2>strace2.txt
Eles terão todos os detalhes de todas as operações open() , close() e read() executadas pelo processo. O que você quer ver é que strace1.txt (quando o arquivo foi passado como argumento e não com redirecionamento de entrada) contém estas linhas:
open("file", O_RDONLY) = 3
read(3, "foo\n", 16384) = 4
Isso significa que o arquivo file foi aberto e anexado ao descritor de arquivo 3 . Em seguida, a string foo\n foi lida de 3 . A parte equivalente da saída strace ao usar o redirecionamento de entrada é:
read(0, "foo\n", 16384) = 4
Não há uma chamada open() correspondente, em vez disso, a string foo\n está sendo lida de 0 , a entrada padrão 1 .
1 Por padrão, 0 é a entrada padrão, 1 é a saída padrão e 2 é o erro padrão. Isto, por sinal, é porque file foi aberto como 3 , que foi o próximo disponível.