2013-04-04 45 views
0

我有以下bash腳本。從當前目錄中的某個類型的所有文件中刪除最後n行,遞歸

for i in **/*.h; do head $i -n -2 > $i.tmp && mv $i.tmp $i -f; done 

其目的是運行當前目錄中的每個.h文件,並從該文件中刪除最後兩行。

但是,這隻能按照預期方式在直接位於當前目錄的子文件夾中的文件上工作,但它不處理子文件夾等子文件夾內的文件,所以./foo/foobar.h會被處理,但./foo/bar/foobar.h或for/bar/foobar/.foobar.h不。

爲此我已經嘗試過這種方式:

for i in 'find -name *.h'; do head $i -n -2 > $i.tmp && mv $i.tmp $i -f; done 

這失敗,因爲> $ i.tmp是模糊的

應該怎樣我的腳本的外觀,使其處理目錄中的所有頭文件,不管它們在子文件夾中的嵌套程度如何?

編輯: 如果直接EOF之前的原始文件一直沒有一個換行符,工作第一腳本從上面(也從答案的sed替代)將增加一個,所以如果EOF之前換行不需要的話,它已被刪除後:

for i in **/*.h; do head $i -n -2 > $i.tmp && mv $i.tmp $i -f && truncate --size=-2 $i; done 

大小應該是-2 CRLF(視窗風格)換行和-1兩個,CR(舊的MacOS風格)和LF(UNIX風格),行尾

當然這種方法也會在eof之前刪除一個換行符,這個換行符已經在

之前如果你有

shopt -s globstar 

啓用

回答

1

你的第一個片段應該工作。

globstar

如果設置,在一個文件名擴展的上下文中使用的模式「**」將匹配的所有文件和零個或多個目錄和子目錄。如果模式後面跟有「/」,則只有目錄和子目錄匹配。

http://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html

+0

確實:作品像一個魅力。 – Kaiserludi 2013-04-04 19:01:21

+0

btw:你有什麼想法,爲什麼globstar在bash4中默認沒有啓用? – Kaiserludi 2013-04-04 19:02:06

+0

取決於您的發行設置和您自己的設置。它在archlinux上默認啓用。 – 2013-04-04 19:19:02

1
find -name '*.h' -exec sed -i 'N;$!P;$!D;$d' '{}' ';' 

這將刪除所有.h文件的最後兩行,並消除了對重定向文件和臨時文件的需要,因爲它編輯到位的文件。它還將處理包含空格的文件名和路徑。

+0

這不是真的,'sed'在後臺爲你創建臨時文件。 – 2013-04-04 18:37:32

+0

@sputnick:你說得對。我的意思是顯式的臨時文件,它使你的單行文件更長,更容易出現異常文件名的錯誤。 – 2013-04-04 18:46:27

+0

phew - 我沒有真正得到這樣的語法:例如你的代碼沒有指定任何數字,那麼sed如何知道要刪除多少行? – Kaiserludi 2013-04-04 19:07:14

相關問題