2017-08-10 59 views
0

最近我遇到了一個奇怪的bash腳本,它用於從find -exec內部調用一個自定義bash函數。我開發了以下簡單的腳本來演示我需要解釋的功能。`find -exec`裏面這個奇怪的語法是什麼?

在以下示例中,將爲每個find結果調用函數foo

foo()                                     
{ 
    echo "[email protected]" 
} 
export -f foo 

find . -exec bash -c 'foo "[email protected]"' bash {} \; 

有人可以解釋如何解釋-exec之後的部分?


UPDATE:

爲了進一步簡化此,如上述出口foo後,得到以下用於每個find結果來執行(假定存在一個名爲my_file的文件)。

bash -c 'foo "$#"' bash my_file 

並且這產生輸出myfile。我不明白這是如何工作的。第二個bash在那裏做什麼?任何詳細的解釋讚賞。

(請注意,這個問題是不是find命令也請忽略的功能foo的功能,我只是想出口一些功能)

回答

3

要了解你需要知道的4件事:

  1. find操作-exec允許您在找到的文件和目錄上應用命令。

    BASH(1) 
    ... 
    OPTIONS 
    ... 
         -c  If the -c option is present, then commands are read from 
           the first non-option argument command_string. 
           If there are arguments after the command_string, they 
           are assigned to the positional parameters, starting with $0. 
    
    ... 
    
    If bash is started with the -c option, then $0 is set to the first 
    argument after the string to be executed, if one is present. 
    Otherwise, it is set to the filename used to invoke bash, as given 
    by argument zero. 
    
  2. bash[email protected]膨脹,所有位置參數($1$2 ...)開始參數$1

  3. 如下-cbash選項記錄。

  4. bash函數中,位置參數是調用時傳遞給函數的參數。

所以,你的情況,對於每一個找到的文件或目錄執行的命令是:

bash -c 'foo "[email protected]"' bash <the-file> 

的位置參數,因此設置爲:

$0 = bash 
$1 = <the-file> 

bash是問在這種情況下執行'foo "[email protected]"'"[email protected]"首先擴展爲"<the-file>"。所以,函數foo被調用一個參數:"<the-file>"。在功能foo上下文中的位置參數是這樣的:

$1 = "<the-file>" 

echo "[email protected]"和作爲膨脹echo "<the-file>"

所有這些只是打印所有找到的文件或目錄的名稱。這幾乎是如果你有任何的:

find . -exec echo {} \; 
find . -print 
find . 
find 

(用於find版本接受最後一個)。

幾乎就好像,因爲如果文件或目錄名稱包含空格,這取決於您對find的用法和引號,您將得到不同的結果。因此,如果您打算擁有更復雜的foo函數,則應注意引號。例子:

$ touch "filename with spaces" plain 
$ ls -1 
filename with spaces 
plain            # 2 files 
$ foo() { echo "[email protected]"; }        # print arguments 
$ find . -type f 
./filename with spaces 
./plain 
$ find . -type f -exec bash -c 'foo "[email protected]"' bash {} \; 
./filename with spaces 
./plain 
$ find . -type f -exec bash -c 'foo [email protected]' bash {} \; 
./filename with spaces 
./plain 

3個find命令顯然做相同的,但:

$ bar() { echo $#; }         # print number of arguments 
$ wc -w < <(find . -type f) 
4             # 4 words 
$ find . -type f -exec bash -c 'bar "[email protected]"' bash {} \; 
1             # 1 argument 
1             # per file 
$ find . -type f -exec bash -c 'bar [email protected]' bash {} \; 
3             # 3 arguments 
1             # 1 argument 

隨着find . -type f -exec bash -c 'bar "[email protected]"' bash {} \;,第一個文件名被傳遞給函數bar作爲一個單獨的參數,而在所有其他情況下,被視爲3個獨立的論點。

+0

@Leon Ooops,謝謝。固定。 –

+0

BTW,我收回我給予好評,因爲海事組織,(更新)回答的第二部分沒有解決OP的問題,因此可能有些誤導 – Leon

+0

@Leon沒問題。我明白你的觀點。我添加了第二部分,因爲我懷疑真正的'foo'函數比OP顯示的要複雜得多(否則,這將是無用的)。如果我沒有錯,它確實會有所作爲......我試圖讓它更清晰一些。 –

相關問題