2012-12-12 62 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