find一个shell函数?

有没有办法find执行我在shell中定义的函数? 例如:

 dosomething () { echo "doing something with $1" } find . -exec dosomething {} \; 

其结果是:

 find: dosomething: No such file or directory 

有没有办法find-exec看到dosomething

由于只有shell知道如何运行shell函数,所以你必须运行一个shell来运行一个函数。 您还需要使用export -f将您的函数标记为导出,否则子shell将不会inheritance它们:

 export -f dosomething find . -exec bash -c 'dosomething "$0"' {} \; 
 find . | while read file; do dosomething "$file"; done 

{}添加引号,如下所示:

 export -f dosomething find . -exec bash -c 'dosomething "{}"' \; 

这样可以纠正由find返回的特殊字符造成的任何错误,例如名称中带有圆括号的文件。

Jak的回答很好,但有一些容易克服的缺陷:

 find . -print0 | while IFS= read -r -d '' file; do dosomething "$file"; done 

这使用null作为分隔符而不是换行符,因此使用换行符的文件名将会起作用。 它也使用-r标志来禁用反斜杠转义,而不使用文件名中的反斜杠将不起作用。 它也清除了IFS以便不会丢弃名称中潜在的空白空格。

让脚本调用它自己,将每个find的项作为parameter passing:

 #!/bin/bash if [ ! $1 == "" ] ; then echo "doing something with $1" exit 0 fi find . -exec $0 {} \; exit 0 

当你自己运行脚本时,它会find你正在查找的内容,并调用自己将每个查找结果作为parameter passing。 当脚本以参数运行时,它会执行参数上的命令,然后退出。

处理结果批量

为了提高效率,许多人使用xargs来批量处理结果,但这是非常危险的。 因为有一个替代方法引入到find ,批量执行结果。

请注意,这种方法可能会带来一些警告,比如POSIX中的一个要求 – 在命令的末尾find {}

 export -f dosomething find . -exec bash -c 'for f; do dosomething "$f"; done' _ {} + 

find会将许多结果作为parameter passing给bash的单个调用, for -loop遍历这些参数,在每个参数上执行函数dosomething

上面的解决scheme启动$1参数,这就是为什么有一个_ (它代表$0 )。

逐一处理结果

以同样的方式,我认为最好的答案应该被纠正为是

 export -f dosomething find . -exec bash -c 'dosomething "$1"' _ {} \; 

这不仅更为理智,因为参数应该始终以$1开始,而且如果find返回的文件名对shell有特殊的含义,使用$0也可能导致意外的行为。

对于那些正在寻找一个bash函数来执行当前目录中所有文件的给定命令的人,我已经从上面的答案中编译了一个:

 toall(){ find . -type f | while read file; do "$1" "$file"; done } 

请注意,它会打破包含空格的文件名 (见下文)。

作为一个例子,采取这个function:

 world(){ sed -i 's_hello_world_g' "$1" } 

假设我想在当前目录中的所有文件中将hello的所有实例更改为world。 我会做:

 toall world 

为了安全使用文件名中的任何符号,请使用:

 toall(){ find . -type f -print0 | while IFS= read -r -d '' file; do "$1" "$file"; done } 

(但你需要一个处理-print0find ,例如GNU find )。

以这种方式执行一个函数是不可能的。

为了克服这个问题,你可以把你的函数放在一个shell脚本中,然后通过find调用它

 # dosomething.sh dosomething () { echo "doing something with $1" } dosomething $1 

现在用它来查找:

 find . -exec dosomething.sh {} \; 

把函数放在一个单独的文件中,并find执行。

Shell函数在它们定义的shell内部; find将永远无法看到他们。

不直接,不。 查找是在一个单独的进程中执行,而不是在你的shell中执行。

创build一个与你的函数完成相同工作的shell脚本,并find-exec

我发现最简单的方法如下,重复一个单一的两个命令

 func_one () { echo "first thing with $1" } func_two () { echo "second thing with $1" } find . -type f | while read file; do func_one $file; func_two $file; done 

我会完全避免使用-exec 。 为什么不使用xargs

 find . -name <script/command you're searching for> | xargs bash -c