Acabei de aprender um truque para criar um novo arquivo com o cat
comando. Pelos meus testes, se a última linha não for seguida por uma nova linha, terei que digitar ctrl+dduas vezes para finalizar a entrada, conforme demonstrado abaixo.
[root@192 ~]# gato > teste uma b ctrl+d[root@192 ~]# gato > teste uma b ctrl+dctrl+d[root@192 ~]#
Isso é esperado? Por que esse comportamento?
Sim, é esperado.
Dizemos que Ctrl-D faz
cat
ver "fim do arquivo" na entrada, e então para de ler e sai, mas isso não é verdade. Como isso está no terminal, não há "fim" real e, na verdade, não é realmente "fim de arquivo" que já foi detectado, mas nenhumread()
byte de zero.Normalmente, a
read()
chamada do sistema não retorna zero bytes, exceto quando se sabe que não há mais disponível, como no final de um arquivo. Ao ler de um soquete de rede onde não há dados disponíveis, espera-se que novos dados cheguem em algum ponto, então, em vez dessa leitura de zero byte, a chamada do sistema bloqueará e aguardará a chegada de alguns dados ou retornará um erro dizendo que iria bloquear. Se a conexão foi encerrada, ela retornaria zero bytes. Então, novamente, mesmo em um arquivo, ler no (ou passado) o final não é um final interminavelmente final, pois outro processo poderia gravar algo no arquivo para torná-lo mais longo, após o qual uma nova tentativa de leitura retornaria mais dados. (Isso é o que uma implementação simples detail -f
faria.)Para muitos casos de uso, tratar "zero bytes lidos" como "final de arquivo detectado" funciona bem o suficiente para que sejam considerados efetivamente a mesma coisa na prática.
O que o Ctrl-D faz aqui é dizer ao driver do terminal para repassar tudo o que recebeu até agora, mesmo que ainda não seja uma linha completa. No início de uma linha, isso é tudo de zero bytes, que é detectado como um EOF. Mas depois da letra
b
, o primeiro Ctrl-D envia ob
, e então o próximo envia os zero bytes inseridos após ob
, e que agora é detectado como o EOF.Você também pode ver o que acontece se você apenas executar
cat
sem um redirecionamento. Vai ficar mais ou menos assim, as partes em itálico são o que eu digitei:Quando Ctrl-D é pressionado,
cat
obtém a entradafoo
, imprime de volta e continua aguardando a entrada. A linha será semelhante afoofoo
, e não há nova linha depois disso, então o cursor permanece lá no final.Algumas palavras sobre.
Tanto quanto eu posso dizer de uma rápida olhada no código-fonte ,
cat
usa um buffer para otimizar seu fluxo de trabalho. Referindo-se ao comportamento dacat
invocação simples, da entrada padrão e sem opções especiais de linha de comando:Isso significa que se você executar o seu
cat> test
e simplesmente entrar Ctrl-D , você criará um arquivo vazio (nomeadotest
) no diretório atual, ou você esvaziará o arquivo se ele já existir, sem a necessidade de um segundo Ctrl-D .Além do escopo desta questão, mas não tão remoto: deve-se notar que se você estiver enviando caracteres para uma instância de terminal/shell, um segundo desnecessário Ctrl-Dpode causar uma saída indesejada (principalmente conectada ao exemplo acima).