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.