2015-09-10 55 views
0

我想使用bash函數中的find -exec。 我知道我需要終止-exec{} \;,但我找不到正確的方法!Bash:從函數中查找-exec

我想:

find $SEARCHPATH -name \"${FILEPAT}.[ch]\" -exec grep --color -aHn \"$GREPPATTERN\" {} \; 
find $SEARCHPATH -name \"${FILEPAT}.[ch]\" -exec grep --color -aHn \"$GREPPATTERN\" '{}' \; 
find $SEARCHPATH -name \"${FILEPAT}.[ch]\" -exec grep --color -aHn \"$GREPPATTERN\" \{\} \; 
find $SEARCHPATH -name \"${FILEPAT}.[ch]\" -exec grep --color -aHn \"$GREPPATTERN\" '{}' ';' 

與其他很多,但我不能得到任何工作。 大多數時候,我得到find: missing argument to '-exec'find接受的語法我沒有得到任何結果一樣簡單的要求:

find . -name "*.[ch]" -exec grep --color -aHn "e" {} \; 

會有人幫助我嗎? 謝謝!

回答

2

請勿繞過參數引號 - 當您這樣做時,引號將被視爲參數的一部分,例如在文件名中查找帶有實際引號的文件。使用這樣的事情:

f() { 
    searchpath=$1 
    filepat=$2 
    greppattern=$3 
    find "$searchpath" -name "$filepat.[ch]" -exec grep --color -aHn "$greppattern" {} \; 
} 

[編輯]擴大我的意見對報價被視爲參數的一部分:在一個命令行報價如何影響它們內部的文本進行解析。雙引號允許變量引用('$ varname`)被擴展和一些其他的東西,但沒有其他的東西。一旦它們產生了這種效果,它們就會被移除(即它們不會傳遞給命令本身)。看到這一點,讓我們來定義,只是打印其參數的函數,看看它實際上是從各種命令行接收:

$ printargs() { printf " <%s>\n" "[email protected]"; } 
$ printargs one two 
    <one> 
    <two> 
$ printargs "one" "two" # The quotes will be removed before printargs sees them 
    <one> 
    <two> 
$ printargs "one two" # The quotes make the two words into one argument, but again aren't passed on to printargs 
    <one two> 
$ printargs "one" 'two' three # Single-quotes are also removed 
    <one> 
    <two> 
    <three> 

類似的事情發生與變量:

$ var="one two" # Note that the quotes are removed before the value is stored in $var 
$ printargs $var # Variable is substituted, then its value is parsed into separate words 
    <one> 
    <two> 
$ printargs "$var" # Double-quotes here allow the variable to be expanded, but prevent further parsing 
    <one two> 
$ printargs '$var' # Single-quotes prevent even variable expansion 
    <$var> 

如果你逃跑的報價但是,他們沒有任何這些影響;他們只是作爲參數的一部分:

$ printargs \"one\" \'two\' \"three four\" 
    <"one"> 
    <'two'> 
    <"three> 
    <four"> 
$ printargs \"$var\" 
    <"one> 
    <two"> 

......這幾乎從來沒有你想要的。特別是,隨着find命令:

$ searchpath=. 
$ filepat='*' 
$ greppattern='#ifdef' 
$ printargs "$searchpath" -name "$filepat.[ch]" -exec grep --color -aHn "$greppattern" {} \; 
    <.> 
    <-name> 
    <*.[ch]> 
    <-exec> 
    <grep> 
    <--color> 
    <-aHn> 
    <#ifdef> 
    <{}> 
    <;> 
$ printargs "$searchpath" -name \"$filepat.[ch]\" -exec grep --color -aHn \"$greppattern\" {} \; 
    <.> 
    <-name> 
    <"*.[ch]"> 
    <-exec> 
    <grep> 
    <--color> 
    <-aHn> 
    <"#ifdef"> 
    <{}> 
    <;> 

...在第二個(包含轉義引號)的報價傳遞給find,並把它們作爲文件名模式的一部分,尋找與雙文件名字中的引號。如果它找到了任何東西,那麼grep命令會發生同樣的事情 - 它會尋找#ifdef的周圍有雙引號。

+0

非常感謝你的工作!還有一個問題:當你說「引號被視爲論證的一部分」時,我不明白你的意思。你是指發現的論點?如果是這樣,爲什麼我直接在shell中需要引號?再次感謝! – Plouff

+1

@Plouff:查看編輯 –

+0

哇!非常感謝你的詳細解答!我意識到「」和「'之間關於變量擴展的區別,但我從來沒有聽說過這個背後的真正機制。 'var =「one two」'的部分讓我大開眼界。再次感謝你! – Plouff