2012-06-11 60 views
1

我看過很多次,如果我想執行的東西在所有子目錄我應該運行類似於下列之一:應用腳本子目錄

find . -name '*' -exec command arguments {} \;

find . -type f -print0 | xargs -0 command arguments

find . -type f | xargs -I {} command arguments {} arguments

問題是,它與corefunctions運行良好,但不是如預期的那樣,當命令是用戶定義的函數或腳本。如何解決它?

所以,我在找的是一行代碼或腳本中,我可以爲myfunctionmyscript.sh更換command和它關係到每一個子目錄從當前目錄並執行上述功能或腳本那裏,不管爭論我供應。

用另一種方式解釋,我想要在所有的子目錄上工作,就像for file in *; do command_myfunction_or_script.sh arguments $file; done在當前目錄上工作一樣。

回答

1

你給的例子,如:

find . -name '*' -exec command arguments {} \; 

不要去每一個子目錄從當前目錄並執行command那裏,而是從當前目錄的路徑,每個文件執行command被查找列爲參數。

如果你想要的是真正改變目錄,然後執行一個腳本,你可以嘗試這樣的事:

STDIR=$PWD; IFS=$'\n'; for dir in $(find . -type d); do cd $dir; /path/to/command; cd $STDIR; done; unset IFS 

這裏當前目錄保存到STDIR和bash的內部字段分隔符設置爲換行符這樣的名字不會在空格上分割。然後,對於find返回的每個目錄(-type d),我們將cd複製到該目錄,執行該命令(使用此處的完整路徑作爲更改目錄會破壞相對路徑),然後再回到起始目錄。

+0

這很棒。我適應了這個:'STDIR = $ PWD;在$(find * -prune -type f 2> &-); do命令中執行「$ file」; done; cd「$ STDIR」;對於$中的dir(find。-type d 2> &-); do cd「$ dir」但是當文件或目錄名稱中有空格時會出現問題我該如何解決這個問題? – Strapakowsky

+1

您可以通過將bash Internal Field Separator更改爲換行來解決此問題,這樣名稱就不會在空格上分割。更新我的答案以顯示此信息,希望它有幫助! –

+0

...但是如果在文件名中有換行符,該怎麼辦? – kojiro

1

可能有一些使用find函數的方法,但它不會非常優雅。如果你有bash的4,你可能想要做的是使用globstar:

shopt -s globstar 
for file in **/*; do 
    myfunction "$file" 
done 

如果您正在尋找與POSIX或舊版本的bash的兼容性,你將被迫源文件中定義的函數時,你調用bash。所以像這樣:

find <args> -exec bash -c '. funcfile; 
    for file; do 
     myfunction "$file" 
    done' _ {} + 

但這只是醜陋。當我到達這一點時,我通常只是將我的功能放在我的PATH上的一個腳本中,並與它一起生活。

2

而不是-exec,請嘗試-execdir

這可能是因爲在某些情況下,你需要使用bash

foo() { echo $1; } 
export -f foo 
find . -type f -name '*.txt' -exec bash -c 'foo arg arg' \; 

最後一行可能是:

find . -type f -name '*.txt' -exec bash -c 'foo "[email protected]"' _ arg arg \; 

根據可能需要擴大和當什麼ARGS。下劃線代表$0

如果需要的話,您可以使用-execdir,我有-exec

1

如果你想使用bash函數,這是一種方法。

work() 
{ 
    local file="$1" 
    local dir=$(dirname $file) 
    pushd "$dir" 
    echo "in directory $(pwd) working with file $(basename $file)" 
    popd 
} 
find . -name '*' | while read line; 
do 
    work "$line" 
done