2011-01-07 166 views
17

如何列出不以换行符结尾的普通文本(.txt)文件名?如何列出不以换行符结尾的文件?

例如为:列表(输出)这个文件名:

$ cat a.txt 
asdfasdlsad4randomcharsf 
asdfasdfaasdf43randomcharssdf 
$ 

,并没有列出(输出)这个文件名:

$ cat b.txt 
asdfasdlsad4randomcharsf 
asdfasdfaasdf43randomcharssdf 

$ 
+0

你只是在寻找一个文件夹的文件的宽屏幕显示下来?你的问题不是很清楚上面的例子.. – James 2011-01-07 23:05:56

+2

“正常txt”是什么意思?你是在谈论以*空行*(\ n \ n)结尾的文件还是只以换行符结尾的文件?您可以使用`od -c filename`来打印文件的明确表示。 – jfs 2011-01-07 23:42:30

+1

只是为了强调:换行符*不与*空白*行相同。换行符是一个单独的字符 - 它划定了我们所看到的“行”。空白行只是一个没有字符的“行”,通常是2个连续的换行符,没有任何中间字符,或者是以换行符开始的文件中的第一行。有些人呼叫仅包含空格“空白”行的行,并为2个连续换行字符保留“空行”一词。你应该清楚你想要什么。 – jw013 2013-07-18 21:00:22

回答

2

这是缺憾;肯定有人可以做得更好:

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.这回答了标题中的问题,它与正文中的问题不同(正在查找以\ n \ n结尾的文件)。

2

这应该做的伎俩:

#!/bin/bash 

for file in `find $1 -type f -name "*.txt"`; 
do 
     nlines=`tail -n 1 $file | grep '^$' | wc -l` 
     if [ $nlines -eq 1 ] 
       then echo $file 
     fi 
done; 

这样调用它:./script dir

例如./script /home/user/Documents/ - >列出/home/user/Documents\n结尾的所有文本文件。

+0

第一个改进是在之前放置'IFS = $'\ n'`。它允许用空格处理文件。第二个改进是用`$ nlines -eq 0`替换`$ nlines -eq 1`,因为作者需要“文件名,**不会以换行符结束**”。 – 2015-04-17 12:52:58

7

试试这个:

find -type f -exec sh -c '[ -z "$(sed -n "\$p" "$1")" ]' _ {} \; -print 

将打印为空白行结尾的文件的文件名。要打印未以空行结尾的文件,请将-z更改为-n

+1

如果存在包含空格的文件名,那么使用`for ... find ... do`的答案将会失败。 – 2011-01-07 23:33:45

+1

你对'for .. find..`正确。http://mywiki.wooledge.org/BashPitfalls#for_i_in_.24.28ls_.2A.mp3.29 – jfs 2011-01-07 23:46:01

1

另一种选择:

$ find . -name "*.txt" -print0 | xargs -0I {} bash -c '[ -z "$(tail -n 1 {})" ] && echo {}' 
0

由于您的问题有perl的标签,我会后它使用一个答案吧:

find . -type f -name '*.txt' -exec perl check.pl {} + 

其中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); 
} 

这个Perl脚本只是打开一个,每次一个,作为参数传递的文件和只读倒数第二个字符;如果它不是换行符,它只是打印出文件名,否则它什么也不做。

17

使用pcregrep,grep的的Perl兼容的正则表达式版本使用,如果最后一行有一个换行符,可以用来匹配(或不匹配)-M标志,它支持多行模式:

pcregrep -LMr '\n$' . 

在上面的例子中,我们要求在当前目录(.)中递归搜索(-r)列出不匹配的文件(-L)我们的多行(-M)正则表达式在文件末尾寻找换行符('\n$'

更改-L-l会列出其中有新行的文件。

14

好吧轮到我了,我给它一个尝试:

find -type f -print0 | xargs -0 -L1 bash -c 'test "$(tail -c 1 "$0")" && echo "No new line at end of $0"' 
1

这个例子对我的作品在OSX(许多上述溶液中没有)

for file in `find . -name "*.java"` 
do 
    result=`od -An -tc -j $(($(ls -l $file | awk '{print $5}') - 1)) $file` 
    last_char=`echo $result | sed 's/ *//'` 
    if [ "$last_char" != "\n" ] 
    then 
    #echo "Last char is .$last_char." 
    echo $file 
    fi 
done 
3

如果您正在使用' ACK”(http://beyondgrep.com)作为替代到grep,你只要运行这个:

ack -v '\n$' 

它实际上搜索所有线路不匹配(-v)行尾的换行符。

1

本页面上的大多数解决方案都不适合我(FreeBSD 10.3 amd64)。伊恩·威尔的 OSX解决方案确实几乎总是工作,但相当难走: - (

有一个简单的解决方案,它几乎总是工作过:(如果$ f是文件):sed的

-i'-e“$ A \”“$ F”

有一个与sed的解决方案的一个主要问题:它永远不会让你有机会 只检查(而不是追加一个换行符)

上述两种解决方案对于DOS文件都是失败的,我认为最可行的解决方案就是prob 我自己开发的: - )

这里是基本的sh脚本,它结合了file/unix2dos/tail。在 生产,你可能需要在引号中,用“$ F”和取尾输出 (嵌入名为最后的shell变量)为\“$ F \”

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 

希望这可以帮助别人。

相关问题