2010-07-16 78 views
9

我有大量的源文件,最後都沒有換行符。如何解決大量文件的「文件末尾沒有換行符」警告?

如何自動添加換行符到每個換行符的結尾?

有些可能已經有換行符,所以只能在必要時添加。

我可能不是在尋找代碼本身,而只是在終端中運行以添加必要的換行符(或某種編程或開發工具)。

回答

3

爲了方便起見,將諾曼的答案轉換爲分離式單行程。

for i in * ; do echo $i; \ 
if diff /dev/null "$i" | tail -1 | \ 
    grep '^\\ No newline' > /dev/null; then echo >> "$i"; \ 
fi; done 

替換*與任何你想要的文件模式,例如*.c

,另一個只是告訴你哪些文件被破壞:

for i in * ; do \ 
if diff /dev/null "$i" | tail -1 | \ 
    grep '^\\ No newline' > /dev/null; then echo $i; \ 
fi; done 
+0

這些解決方案都不適用於我 – 2012-11-10 10:09:58

+1

如果您希望它以遞歸方式進行交換,可以交換'*'用'$(find。-type f)'或'$(找到 -type f -name )' – durron597 2013-08-30 14:53:40

7

如果你有機會獲得Unix工具,你可以運行diff找出哪些文件缺乏一個換行符,然後將其追加:

#!/bin/sh 
for i 
do 
    if diff /dev/null "$i" | tail -1 | grep '^\\ No newline' > /dev/null 
    then 
    echo >> "$i" 
    fi 
done 

我靠diff生產具有在\消息第一列tail給我最後一行diff的輸出,並且grep告訴我最後一行是否是我正在查找的消息。如果一切正常,則echo會生成一個換行符,>>會將其附加到文件"$i"。如果文件名中有空格,"$i"左右的引號可以確保事情仍然有效。

+2

不錯,但是grep會返回一個本地化的消息,比如「\ Brak znaku nowej linii(etc.)」。另外,diff輸出整個文件。我會使用'tail -1 $ f | grep'\ n''的條件(在我的盒子上工作)。 – 2012-12-12 12:46:59

+0

@TomaszGandor:'tail -1 filename | grep'\ n'似乎總是在我的mac上返回一個錯誤的結果,不管是否有尾隨的換行符。 – Gino 2017-05-27 14:03:39

2

OK,在評論抱怨後,有我更好的解決方案 首先,你要知道,這些文件丟失換行符:

find -type f -exec sh -c "tail -1 {} | xxd -p | tail -1 | grep -v 0a$" ';' -print 

不超快速(要求每個文件一對夫婦的進程),但它的實際用途確定。

現在,當你擁有了它,你不妨加入新行,與其他-exec

find -type f -exec sh -c "tail -1 {} | xxd -p | tail -1 | grep -v 0a$" ';' -exec sh -c "echo >> {}" ';' 

可能的陷阱:

  • 如果文件名是不好的,例如他們有空間,您可能需要tail -1 \"{}\"。 或確實找對了嗎?

  • 您可能想要添加更多的過濾來查找,如-name \*py等。

  • 想想可能的DOS/Unix換行在使用之前亂七八糟(首先修復)。

編輯:

如果你不喜歡這些命令的輸出(呼應一些十六進制),加-q到grep:

find -type f -exec sh -c "tail -1 {} | xxd -p | tail -1 | grep -q -v 0a$" ';' -print 
find -type f -exec sh -c "tail -1 {} | xxd -p | tail -1 | grep -q -v 0a$" ';' -exec sh -c "echo >> {}" ';' 
+1

這是*巨大的*矯枉過正。 – tripleee 2015-08-29 09:29:11

0

由於指揮本地化Tim和諾曼答案應該使用'LANG = C'前綴進行改進,以便有機會與每個具有任何區域參數的系統匹配'無換行'模式

這確保了結束空行把這個腳本的命令行上的每個文件:

#!/bin/sh -f 
for i in $* ; do echo $i; \ 
if LANG=C diff /dev/null "$i" | tail -1 | \ 
    grep '^\\ No newline' > /dev/null; then echo >> "$i"; \ 
fi; done 

而這個腳本檢測缺乏的是文件:

#!/bin/sh -f 
for i in $* ; do \ 
if LANG=C diff /dev/null "$i" | tail -1 | \ 
    grep '^\\ No newline' > /dev/null; then echo $i; \ 
fi; done 
1

嘗試前路:

ex -s +"bufdo wq" *.c 

,並遞歸(啓用a new globbing option):

ex -s +"bufdo wq" **/*.c 

這相當於vi -es。更改*.c以擴展您的興趣。

如果不存在,ex/vi會在保存時自動附加新行。

0

找到工具後,做這個工作沒有運氣。我決定寫我自己的

這是我的Python腳本來完成這項工作

只追加(\ r \ n)與文件不包含(\ n)的在文件的結尾

https://github.com/tranhuanltv/append_newline

用法:append_newline.py .C ./projects ./result_dir

製作引入請求,如果你想

+0

這是非常值得懷疑的 - 從END開始尋找-1是可以的,但是你可以用這種方法輕鬆地混合使用Unix和DOS換行符...... – 2016-04-01 07:26:57

0

我很驚訝沒有人已經提到像Awk這樣的許多簡單的文本處理工具會添加一個換行符作爲副作用。這是一個簡單的循環,只有在實際添加換行符時纔會覆蓋文件。

for f in *; do 
    awk 1 "$f" >tmp 
    cmp -s tmp "$f" || mv tmp "$f" 
done 
rm -f tmp 

(臨時文件顯然是有點疣。)

IDEone演示:http://ideone.com/HpRHcx

0
pcregrep --recursive --exclude-dir=.git \ 
    --files-without-match --multiline '\n\z' . | 
    while read k ; do echo >> "$k"; done 

這裏涉及到幾個步驟:

  1. 遞歸查找文件
  2. 檢測哪些文件缺乏一個尾隨新行
  3. 遍歷每個那些文件
  4. 追加新行

步驟1歷來與find做(以下 Unix的傳統「每個工具做一兩件事,做的很好」),但由於pcregrep具有內置的支持,我很舒服使用它。我小心避免亂七八糟的.git文件夾。

步驟2用多正則表達式匹配有一個最後的換行的文件,並打印該匹配文件名來完成。

步驟3是用while/read循環而不是for/in完成的,因爲後者失敗了包含空格的文件名和極長的文件列表。

步驟4是一個簡單的回聲,遵循@ norman-ramsey的方法。

h/t @ anthony-bush https://stackoverflow.com/a/20687956/577438爲pcregrep建議。

1

我使用find代替for f in *,因爲它是遞歸的,問題是關於「大量的源文件」。

由於性能方面的原因,我使用的是while read而不是find -execxargs,它每次都會節省產卵shell進程。

我正在利用反引號操作符正在返回命令的輸出,「任何尾隨的換行符被刪除」man bash,因此對於正確終止的文件,反引號將爲空,並且回顯將被跳過。

find | read夫婦將無法對包含換行符的文件名,但它很容易,如果需要解決:

find -type f -print0 | while read -d $'\0' f; do [[ `tail -c1 "$f"` ]] && echo >> "$f"; done

0

下面是我的bash腳本的解決方案。它首先檢查文件是否是文本文件。然後,如果它是一個文本文件,它使用tail和od(八進制轉儲)來查看最後一個字符是否是換行符。如果不是,那麼就使用回聲附加一個換行符:

item="$1" 

if file "$item" | egrep '\btext\b' > /dev/null 
then 
    if ! tail -c 1 "$item" | od -b -A n | egrep '\b012\b' > /dev/null 
    then 
     echo "(appending final newline to ${item})" 
     echo >> "$item" 
    fi 
fi 
1

一個簡單的修正對於那些「失蹤」換行符在文件末尾簡單的sed文件;以下修復「就地」(使用「-i」選項)的文件:

find . -type f -exec sed -i -e '$a\' {} \; -print 

說明:找到的所有文件(-type f),運行sed,更改文件就地(-i),給定以下(-e)腳本/表達式匹配文件末尾($),並執行「追加」動作(a\),但實際上並未指定要追加的任何文本(在\之後沒有任何內容)在文件的末尾添加一個換行符,但只有當文件末尾不存在時。打印找到的所有文件(固定或不固定),這可能是不必要的。

主要需要注意的是sed功能因平臺而異,所以-i-e可能會或可能不會被支持/相同;例如較舊的Unix或MacOS的怪異可能需要稍微不同的語法。