Para esclarecer, o caractere LF (também conhecido como \n
ou newline) é a linha delimitador , não é o separador de linha. Uma linha não está terminada, a menos que seja terminada por um caractere de nova linha. Um arquivo que contém apenas a\nb
não é um arquivo de texto válido porque contém caracteres após a última linha. O mesmo para um arquivo que contém apenas a
. Um arquivo que contém a\n
contém uma linha não vazia.
Assim, um arquivo que termina com pelo menos uma linha vazia termina com dois caracteres de nova linha ou contém um único caractere de nova linha.
Se:
tail -c 2 file | od -An -vtc
Gera \n
ou \n \n
, então o arquivo contém pelo menos uma linha vazia à direita. Se não produzir nada, então esse é um arquivo vazio, se gerar <anything-but-
, então terminará em uma linha não vazia. Qualquer outra coisa, não é um arquivo de texto. od
> \n
Agora, para usar isso para localizar arquivos que terminam em uma linha vazia, é eficiente (especialmente para arquivos grandes), pois lê apenas os últimos dois bytes dos arquivos, mas primeiro a saída não é facilmente analisável programaticamente, especialmente considerando que não é consistente de uma implementação de tail
para a próxima, e precisamos executar um od
e um zsh
por arquivo.
find . -type f -size +0 -exec gawk '
ENDFILE{if ($0 == "") print FILENAME}' {} +
(para encontrar arquivos terminados em uma linha vazia) executaria o mínimo de comandos possível, mas significaria ler o conteúdo completo de todos os arquivos.
Idealmente, você precisaria de um shell que pudesse ler o final de um arquivo por si só.
com %code% :
zmodload zsh/system
for f (**/*(D.L+0)) {
{
sysseek -w end -2
sysread
[[ $REPLY = $'\n' || $REPLY = $'\n\n' ]] && print -r -- $f
} < $f
}