Por que esses dois comandos 'cat' resultam de maneira diferente?

12

Vamos supor que infile contém um texto específico, e eu deveria executar o seguinte conjunto de comandos:

exec 3<infile

gato -n <&3

gato -n <&3

A primeira instância do gato exibirá o conteúdo do arquivo, mas a segunda vez não parece estar fazendo nada. Por que eles diferem?

não terrorista
fonte

Respostas:

29

Eles se parecem com o mesmo comando, mas o motivo pelo qual diferem é que o estado do sistema foi alterado como resultado do primeiro comando. Especificamente, o primeiro catconsumiu o arquivo inteiro; portanto, o segundo catnão tem mais nada para ler, atinge o EOF (final do arquivo) imediatamente e sai.

A razão por trás disso é que você está usando exatamente a mesma descrição de arquivo (a que você criou exec < infilee atribuiu ao descritor de arquivo 3) para as duas chamadas de cat. Uma das coisas associadas a uma descrição de arquivo aberto é um deslocamento de arquivo. Portanto, o primeiro catlê o arquivo inteiro, deixa o deslocamento no final e o segundo tenta pegar o final do arquivo e não encontra nada para ler.

jw013
fonte
12

Apenas para adicionar à boa resposta de @ jw013, pode ajudar a perceber que é o mesmo que

{
   cat -n
   cat -n
} < infile

< filesendo curto 0< file, use o descritor de arquivo 0 em vez de 3.

E apenas para confundir um pouco o assunto, esta versão:

exec 3< infile
cat -n /dev/fd/3
cat -n /dev/fd/3

Comporta-se de maneira diferente, dependendo do sistema operacional em que você o executa e do tipo de infile(arquivo normal x pipe x dispositivo ...)

No Solaris e a maioria dos Unices comerciais, um open("/dev/fd/3")é mais ou menos equivalente a um dup(3)(assim < /dev/fd/3é aproximadamente o mesmo que <&3), enquanto no Linux, para arquivos regulares, /dev/fd/3é implementado como um link simbólico para o arquivo original, então open("/dev/fd/3")a abre de novo desde o início ( e possivelmente com bandeiras diferentes do fd 3).

Stéphane Chazelas
fonte