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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 02:24:28  来源:igfitidea点击:

How do I find files that do not end with a newline/linefeed?

linuxperlbash

提问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/Documentsending 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 -zto -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 -Lto -lwould list the files that dohave newlines in them.

更改-L-l将列出其中确实有换行符的文件。

pcregrepcan be installed on MacOS with the homebrew pcrepackage: 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.

希望这可以帮助某人。