2012-12-12 85 views
3

如何在find的exec中運行子命令? 例如,如果我想只能從完整路徑獲得的文件名,並打印出來,我就火了,如何在find中運行子命令exec

find ./ -name "*.csv" -exec echo $(basename {}) \; 

其中回聲子命令基名的父命令。

但結果是相同的,因爲這,

find ./ -name "*.csv" -exec echo {} \; 

我該怎麼辦?

回答

0

一如既往,調用一個shell來運行它。

find ... -exec bash -c "... $1 ..." subshell {} \; 
+0

日Thnx。對於subshel​​l非常天真。我有一個例子嗎? – JohnG

0

@伊格納西奧的是完全正確,albiet偏向特定的外殼,而不是提示有POSIX標準殼....

但是,你正在做的是更有效地用做過濾。即你正試圖找到一種方法來讓find轉換它將要打印的每個路徑名,但是這會導致find找到一個shell進程來查找它匹配的每個文件名!

爲了提高效率,您應該嘗試找到一種方法將find可能生成的路徑名列表轉換爲您希望看到的路徑名稱,並且只需一個額外的過程即可完成此操作。

例如,如果你想看到的是基本名稱(即最終的文件名部分),每個路徑名,那麼你可以用一個(相對)簡單sed命令,你可以管你find輸出通過產生做平凡文件名中所需的列表:

sed '/^[^/]*$/p;s/.*\/\([^/]*\)$/\1/p' 
+0

和格雷格,thnx的答覆。我希望使用基本名稱作爲其他命令的第一個參數,它應該在find的-exec主體內部運行。你建議的任何其他方式? – JohnG

+0

嗯,它取決於命令是什麼,以及它如何操作基本文件名(特別是不知道文件位於何處)。例如,如果命令可以同時接受多個文件名作爲參數,那麼您可以將'sed'的輸出傳遞給'xargs other_command'。如果您確實需要爲每個名稱分別調用該命令(爲什麼?),那麼Ignacio的方法可能是最好的,但您可以通過使用'while read fname;從父shell啓動命令來保存每個名稱的shell調用。在'sed'之後做'循環。 –

8

這是你在找什麼:

find . -name "*.csv" -exec sh -c 'echo $(basename "$1")' sh {} \; 
+0

我不明白'$ 1'和第二個'sh'。爲什麼不使用'find。 -name「* .csv」-exec sh -c'echo $(basename「$ 0」)'{} \;'。這對我來說很完美。 – Tik0

+1

@ Tik0關鍵是一致性。使用$ 0確實可以在這裏工作,但是這樣做會打破$ 0的約定,這意味着正在運行的進程名稱的名稱。例如,Top或者ps會報告奇怪的命令名稱。像for循環這樣更復雜的結構將會失敗。 – jlliagre

+0

沒問題,所以第二個'sh'只是一個佔位符來保持被調用的程序是'sh'的約定(s.t.是第一個)。 – Tik0