尽管它不能直接回答问题,但这是我编写的一个相关脚本,用于检测未以换行符结尾的文件。非常快。
find.-type f|# sort | # sort file names if you like/usr/bin/perl-lne'
open FH, "
$pos = sysseek FH, 0, 2; # seek to EOF
if (!defined $pos) { print " error: $_"; next }
if ($pos == 0) { print " empty: $_"; next }
$pos = sysseek FH, -1, 1; # seek to last char
if (!defined $pos) { print " error: $_"; next }
$cnt = sysread FH, $c, 1;
if (!$cnt) { print " error: $_"; next }
if ($c eq "\n") { print " EOL: $_"; next }
else { print "no EOL: $_"; next }
'
perl脚本从stdin读取(可选排序的)文件名列表,并为每个文件读取最后一个字节,以确定文件是否以换行符结尾。它非常快,因为它避免了读取每个文件的全部内容。对于每个读取的文件,它输出一行,如果发生某种错误,则以“ error:”为前缀,如果文件为空(不以换行符结尾!),则以“ empty:”开头;“ EOL:”(“行”),如果文件以换行符结尾,则为“ no EOL:”(如果文件不以换行符结尾)。
注意:该脚本不处理包含换行符的文件名。如果您使用的是GNU或BSD系统,则可以通过添加-print0来查找,-z进行排序以及-0到perl来处理所有可能的文件名,如下所示:
find.-type f-print0|sort-z|/usr/bin/perl-ln0e'
open FH, "
$pos = sysseek FH, 0, 2; # seek to EOF
if (!defined $pos) { print " error: $_"; next }
if ($pos == 0) { print " empty: $_"; next }
$pos = sysseek FH, -1, 1; # seek to last char
if (!defined $pos) { print " error: $_"; next }
$cnt = sysread FH, $c, 1;
if (!$cnt) { print " error: $_"; next }
if ($c eq "\n") { print " EOL: $_"; next }
else { print "no EOL: $_"; next }
'
当然,您仍然必须想出一种在输出中使用换行符对文件名进行编码的方法(留给读者练习)。
如果需要,可以对输出进行过滤,以将换行符添加到那些没有换行符的文件中,最简单的做法是
echo>>"$filename"
缺少最后一个换行符可能会导致脚本中的错误,因为在读取此类文件时,某些版本的Shell和其他实用程序将无法正确处理缺少的最后一个换行符。
以我的经验,缺少最后一个换行符是由使用各种Windows实用程序来编辑文件引起的。我从未见过vim在编辑文件时会导致缺少最后的换行符,尽管它会报告此类文件。
最后,还有一些更短(但更慢)的脚本,它们可以循环其文件名输入以打印不以换行符结尾的那些文件,例如:
/usr/bin/perl-ne'print "$ARGV\n" if /.\z/'--FILE1 FILE2...