2011-01-07 27 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 

希望這可以幫助別人。

相關問題