Linux 如何查找不以换行符/换行符结尾的文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4631068/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I find files that do not end with a newline/linefeed?
提问by LanceBaynes
How can I list normal text (.txt
) filenames, that don't end with a newline?
如何列出.txt
不以换行符结尾的普通文本 ( ) 文件名?
e.g.: list (output) this filename:
例如:列出(输出)这个文件名:
$ cat a.txt
asdfasdlsad4randomcharsf
asdfasdfaasdf43randomcharssdf
$
and don't list (output) this filename:
并且不要列出(输出)这个文件名:
$ cat b.txt
asdfasdlsad4randomcharsf
asdfasdfaasdf43randomcharssdf
$
回答by ysth
This is kludgy; someone surely can do better:
这很笨拙;肯定有人可以做得更好:
for f in `find . -name '*.txt' -type f`; do
if test `tail -c 1 "$f" | od -c | head -n 1 | tail -c 3` != \n; then
echo $f;
fi
done
N.B. this answers the question in the title, which is different from the question in the body (which is looking for files that end with \n\n I think).
注意这回答了标题中的问题,这与正文中的问题不同(我认为它正在寻找以 \n\n 结尾的文件)。
回答by Andrei Sfrent
This should do the trick:
这应该可以解决问题:
#!/bin/bash
for file in `find -type f -name "*.txt"`;
do
nlines=`tail -n 1 $file | grep '^$' | wc -l`
if [ $nlines -eq 1 ]
then echo $file
fi
done;
Call it this way: ./script dir
这样称呼它: ./script dir
E.g. ./script /home/user/Documents/
-> lists all text files in /home/user/Documents
ending with \n
.
例如./script /home/user/Documents/
-> 列出所有/home/user/Documents
以\n
.
回答by Paused until further notice.
Give this a try:
试试这个:
find . -type f -exec sh -c '[ -z "$(sed -n "$p" "")" ]' _ {} \; -print
It will print filenames of files that end with a blank line. To print files that don't end in a blank line change the -z
to -n
.
它将打印以空行结尾的文件的文件名。要打印不空行改变结尾的文件-z
来-n
。
回答by Diego Torres Milano
Another option:
另外一个选项:
$ find . -name "*.txt" -print0 | xargs -0I {} bash -c '[ -z "$(tail -n 1 {})" ] && echo {}'
回答by marco
Since your question has the perl tag, I'll post an answer which uses it:
由于您的问题具有 perl 标签,我将发布一个使用它的答案:
find . -type f -name '*.txt' -exec perl check.pl {} +
where check.pl is the following:
其中 check.pl 如下:
#!/bin/perl
use strict;
use warnings;
foreach (@ARGV) {
open(FILE, $_);
seek(FILE, -2, 2);
my $c;
read(FILE,$c,1);
if ( $c ne "\n" ) {
print "$_\n";
}
close(FILE);
}
This perl script just open, one per time, the files passed as parameters and read only the next-to-last character; if it is not a newline character, it just prints out the filename, else it does nothing.
这个 perl 脚本每次打开一个,作为参数传递的文件只读取倒数第二个字符;如果它不是换行符,它只会打印出文件名,否则它什么都不做。
回答by Anthony Bush
Use pcregrep, a Perl Compatible Regular Expressions version of grep which supports a multiline mode using -M flag that can be used to match (or not match) if the last line had a newline:
使用 pcregrep,grep 的 Perl 兼容正则表达式版本,它支持使用 -M 标志的多行模式,如果最后一行有换行符,可用于匹配(或不匹配):
pcregrep -LMr '\n$' .
In the above example we are saying to search recursively (-r
) in current directory (.
) listing files that don't match (-L
) our multiline (-M
) regex that looks for a newline at the end of a file ('\n$'
)
在上面的例子中,我们说-r
在当前目录 ( .
) 中递归搜索( ) 列出与 ( -L
) 我们的多行 ( -M
) 正则表达式不匹配的文件,该正则表达式在文件末尾查找换行符 ( '\n$'
)
Changing -L
to -l
would list the files that dohave newlines in them.
更改-L
为-l
将列出其中确实有换行符的文件。
pcregrep
can be installed on MacOS with the homebrew pcre
package: brew install pcre
pcregrep
可以使用 homebrewpcre
包安装在 MacOS 上:brew install pcre
回答by Julien Palard
Ok it's my turn, I give it a try:
好的,轮到我了,我试一试:
find . -type f -print0 | xargs -0 -L1 bash -c 'test "$(tail -c 1 "for file in `find . -name "*.java"`
do
result=`od -An -tc -j $(( $(ls -l $file | awk '{print }') - 1 )) $file`
last_char=`echo $result | sed 's/ *//'`
if [ "$last_char" != "\n" ]
then
#echo "Last char is .$last_char."
echo $file
fi
done
")" && echo "No new line at end of ack -v '\n$'
"'
回答by Ian Will
This example works for me on OSX (many of the above solutions did not)
这个例子在 OSX 上对我有用(上面的许多解决方案都没有)
if file $f | grep 'ASCII text' > /dev/null; then
if file $f | grep 'CRLF' > /dev/null; then
type unix2dos > /dev/null || exit 1
dos2unix $f
last="`tail -c1 $f`"
[ -n "$last" ] && echo >> $f
unix2dos $f
else
last="`tail -c1 $f`"
[ -n "$last" ] && echo >> $f
fi
fi
回答by pelagic
If you are using 'ack' (http://beyondgrep.com) as a alternative to grep, you just run this:
如果您使用 'ack' ( http://beyondgrep.com) 作为 grep 的替代,您只需运行以下命令:
##代码##It actually searches all lines that don't match (-v) a newline at the end of the line.
它实际上搜索所有在行尾不匹配 (-v) 换行符的行。
回答by Manish Jain
Most solutions on this page do not work for me (FreeBSD 10.3 amd64). Ian Will's OSX solution does almost-always work, but is pretty difficult to follow : - (
此页面上的大多数解决方案对我不起作用(FreeBSD 10.3 amd64)。Ian Will 的 OSX 解决方案几乎总是有效,但很难遵循:-(
There is an easy solution that almost-always works too : (if $f is the file) :
有一个简单的解决方案,几乎总是有效:(如果 $f 是文件):
sed -i '' -e '$a\' "$f"
sed -i '' -e '$a\' "$f"
There is a major problem with the sed solution : it never gives you the opportunity to just check (and not append a newline).
sed 解决方案有一个主要问题:它从来没有给你机会只检查(而不是附加换行符)。
Both the above solutions fail for DOS files. I think the most portable/scriptable solution is probably the easiest one, which I developed myself : - )
对于 DOS 文件,上述两种解决方案都失败了。我认为最便携/可编写脚本的解决方案可能是我自己开发的最简单的解决方案:-)
Here is that elementary sh script which combines file/unix2dos/tail. In production, you will likely need to use "$f" in quotes and fetch tail output (embedded into the shell variable named last) as \"$f\"
这是结合 file/unix2dos/tail 的基本 sh 脚本。在生产中,您可能需要在引号中使用 "$f" 并将尾部输出(嵌入到名为 last 的 shell 变量中)作为 \"$f\"
##代码##Hope this helps someone.
希望这可以帮助某人。