2012-07-12 32 views
2

我想在Linux的find命令中使用正則表達式來遞歸地跳入一個龐大的目錄樹,向我展示所有的.c,.cpp和.h文件,但省略了包含某些子字符串的匹配。最終,我想將輸出發送到一個xargs命令,以對所有匹配的文件執行特定處理。我可以通過grep管道輸出find以刪除包含這些子字符串的匹配項,但該解決方案對於包含空格的文件名不起作用。所以我嘗試使用find的-print0選項,它終止每個文件名用一個nul字符而不是一個換行符(空白),並使用xargs -0來期望nul-delimited輸入,而不是空格分隔的輸入,但我無法弄清楚如何通過管道grep過濾器成功地通過nul-delimited find; grep -Z在這方面似乎沒有幫助。如何從Linux的「find」命令的輸出中排除匹配某些模式的目錄?

所以我想我只是寫一個更好的正則表達式爲find,並取消中間grep過濾器...也許sed將是一個替代?

在任何情況下,對目錄的以下的小採樣...

./barney/generated/bam bam.h 
./barney/src/bam bam.cpp 
./barney/deploy/bam bam.h 
./barney/inc/bam bam.h 
./fred/generated/dino.h 
./fred/src/dino.cpp 
./fred/deploy/dino.h 
./fred/inc/dino.h 

...我要輸出到包括所有的.H,.C,和.cpp文件,但不是那些那些出現在'生成'和'部署'目錄中的。

順便說一句,你可以通過切割&粘貼在此整條生產線到您的bash shell創建用於測試的解決方案,這個問題整個測試目錄(名爲fredbarney):

mkdir fredbarney; cd fredbarney; mkdir fred; cd fred; mkdir inc; mkdir docs; mkdir generated; mkdir deploy; mkdir src; echo x > inc/dino.h; echo x > docs/info.docx; echo x > generated/dino.h; echo x > deploy/dino.h; echo x > src/dino.cpp; cd ..; mkdir barney; cd barney; mkdir inc; mkdir docs; mkdir generated; mkdir deploy; mkdir src; echo x > 'inc/bam bam.h'; echo x > 'docs/info info.docx'; echo x > 'generated/bam bam.h'; echo x > 'deploy/bam bam.h'; echo x > 'src/bam bam.cpp'; cd ..; 

這個命令在所有的.H ,.C,和.cpp文件...

find . -regextype posix-egrep -regex ".+\.(c|cpp|h)$" 

...但如果我管其通過xargs的輸出時,「咣噹咣噹」文件分別獲得視爲兩個獨立的(不存在的)的文件名(注意這裏我只是簡單地使用ls作爲我交流的替身tually要與輸出做):

$ find . -regextype posix-egrep -regex ".+\.(c|cpp|h)$" | xargs -n 1 ls 
ls: ./barney/generated/bam: No such file or directory 
ls: bam.h: No such file or directory 
ls: ./barney/src/bam: No such file or directory 
ls: bam.cpp: No such file or directory 
ls: ./barney/deploy/bam: No such file or directory 
ls: bam.h: No such file or directory 
ls: ./barney/inc/bam: No such file or directory 
ls: bam.h: No such file or directory 
./fred/generated/dino.h 
./fred/src/dino.cpp 
./fred/deploy/dino.h 
./fred/inc/dino.h 

所以我可以提高,與-print0和-0參數傳遞給findxargs

$ find . -regextype posix-egrep -regex ".+\.(c|cpp|h)$" -print0 | xargs -0 -n 1 ls 
./barney/generated/bam bam.h 
./barney/src/bam bam.cpp 
./barney/deploy/bam bam.h 
./barney/inc/bam bam.h 
./fred/generated/dino.h 
./fred/src/dino.cpp 
./fred/deploy/dino.h 
./fred/inc/dino.h 

...這是偉大的,但我不希望輸出中的「生成」和「部署」目錄。所以我試試這個:

$ find . -regextype posix-egrep -regex ".+\.(c|cpp|h)$" -print0 | grep -v generated | grep -v deploy | xargs -0 -n 1 ls 
barney fred 

......這顯然不起作用。所以我嘗試使用-Z選項和grep(不知道-Z選項到底是什麼),那也不管用。所以,我想我會寫一個更好的正則表達式find,這是我能想出的最好:

find . -regextype posix-egrep -regex "(?!.*(generated|deploy).*$)(.+\.(c|cpp|h)$)" -print0 | xargs -0 -n 1 ls 

...但慶典不喜歡這樣(*:!未找到事件,無論這意味着),即使這不是一個問題,我的正則表達式似乎沒有在我通常使用的正則表達式測試器網頁上工作。

任何想法,我可以使這項工作?這是我想要的輸出:

$ find . [----options here----] | [----maybe grep or sed----] | xargs -0 -n 1 ls 
./barney/src/bam bam.cpp 
./barney/inc/bam bam.h 
./fred/src/dino.cpp 
./fred/inc/dino.h 

...我想避免腳本&臨時文件,我想可能是我唯一的選擇。

在此先感謝! 馬克

+2

'未找到事件'是因爲'!'被解釋爲'bash'的歷史擴展請求。單引號出現在其中的字符串,或給它一個額外的轉義。我建議單引號! – Sorpigal 2012-07-12 16:27:47

回答

5

這個工作對我來說:

從您的版本
find . -regextype posix-egrep -regex '.+\.(c|cpp|h)$' -not -path '*/generated/*' \ 
     -not -path '*/deploy/*' -print0 | xargs -0 ls -L1d 

的變化是微乎其微的:我單獨添加某些路徑模式的排除,因爲這是比較容易的,我的單引號的東西從外殼隱藏插值。

未找到該事件是因爲!被解釋爲請求歷史擴展bash。解決方法是使用單引號而不是雙引號。

流行測驗:sh中單引號字符串中的特殊字符是什麼?

答:只有'是特殊的(它結束的字符串)。這是最終的安全。

grep-Z(有時也被稱爲--null)使得grep輸出以空字符來代替新行終止。你想要的是-z(有時被稱爲--null-data),它導致grep將它的輸入中的空字符解釋爲換行符而不是換行符。這使得它按預期工作,輸出爲find ... -print0,它在每個文件名後面添加一個空字符,而不是換行符。

如果你做了這種方式:

find . -regextype posix-egrep -regex '.+\.(c|cpp|h)$' -print0 | \ 
    grep -vzZ generated | grep -vzZ deploy | xargs -0 ls -1Ld 

然後輸入grep輸出會一直空分隔,它會正常工作......直到你的源文件中的一個開始被命名爲deployment.cpp,並開始被你的腳本「神祕地」排除在外。

順便提一句,下面是生成測試用例文件集的更好方法。

while read -r file ; do 
    mkdir -p "${file%/*}" 
    touch "$file" 
done <<'DATA' 
./barney/generated/bam bam.h 
./barney/src/bam bam.cpp 
./barney/deploy/bam bam.h 
./barney/inc/bam bam.h 
./fred/generated/dino.h 
./fred/src/dino.cpp 
./fred/deploy/dino.h 
./fred/inc/dino.h 
DATA 

因爲我這樣做無論如何,以驗證我想我會分享並保存你重複。不要做任何事情兩次!這就是電腦的用途。

+0

優秀!謝謝。 – phonetagger 2012-07-12 17:01:56

+0

特別感謝您爲我解決問題的兩種方式。 – phonetagger 2012-07-12 17:05:48

+0

+1非常徹底! – tripleee 2012-07-13 09:03:15

相關問題