bash - 在Linux中查找-exec shell函数?
有没有办法让find执行我在shell中定义的函数? 例如:
dosomething () {
echo "doing something with $1"
}
find . -exec dosomething {} \;
结果是:
find: dosomething: No such file or directory
有没有办法得到find的-exec看到dosomething?
12个解决方案
207 votes
由于只有shell知道如何运行shell函数,因此必须运行shell来运行函数。 您还需要使用export -f标记要导出的函数,否则子shell将不会继承它们:
export -f dosomething
find . -exec bash -c 'dosomething "$0"' {} \;
Adam Rosenfield answered 2019-05-05T18:45:46Z
87 votes
find . | while read file; do dosomething "$file"; done
Jac answered 2019-05-05T18:46:03Z
17 votes
在find中添加引号,如下所示:
export -f dosomething
find . -exec bash -c 'dosomething "{}"' \;
这可以纠正由find返回的特殊字符引起的任何错误,例如,名称中带有括号的文件。
Wagner answered 2019-05-05T18:46:34Z
13 votes
Jak的答案很好,但有一些容易克服的陷阱:
find . -print0 | while IFS= read -r -d '' file; do dosomething "$file"; done
这使用null作为分隔符而不是换行符,因此带有换行符的文件名将起作用。 它还使用-r标志禁用反斜杠转义,没有文件名中的反斜杠将无法正常工作。 它还清除IFS,以便不丢弃名称中潜在的尾随空格。
pajamian answered 2019-05-05T18:47:06Z
8 votes
让脚本调用自己,传递作为参数找到的每个项目:
#!/bin/bash
if [ ! $1 == "" ] ; then
echo "doing something with $1"
exit 0
fi
find . -exec $0 {} \;
exit 0
当您单独运行脚本时,它会找到您要查找的内容并调用自身将每个查找结果作为参数传递。 当脚本使用参数运行时,它会对参数执行命令,然后退出。
Mike Maready answered 2019-05-05T18:47:38Z
6 votes
处理结果大量
为了提高效率,许多人使用$1批量处理结果,但这是非常危险的。 因此,在$0中引入了一种替代方法,可以批量执行结果。
请注意,此方法可能会带有一些警告,例如POSIX-$1中的要求在命令末尾有$0。
export -f dosomething
find . -exec bash -c 'for f; do dosomething "$f"; done' _ {} +
$1将许多结果作为参数传递给单个调用$0,并且find循环遍历这些参数,在每个参数上执行函数dosomething。
上述解决方案在$1开始论证,这就是为什么存在$0(代表find)的原因。
逐个处理结果
以同样的方式,我认为应该纠正被接受的最佳答案
export -f dosomething
find . -exec bash -c 'dosomething "$1"' _ {} \;
这不仅更加明智,因为参数应始终从$1开始,如果find返回的文件名对shell具有特殊含义,则使用$0可能会导致意外行为。
Dominik answered 2019-05-05T18:48:51Z
2 votes
对于那些寻找将在当前目录中的所有文件上执行给定命令的bash函数的人,我已经从上面的答案中编译了一个:
toall(){
find . -type f | while read file; do "$1" "$file"; done
}
请注意,它打破了包含空格的文件名(见下文)。
例如,使用此功能:
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
}
(但是你需要一个处理-print0的find,例如,GNU find)。
Jason Basanese answered 2019-05-05T18:49:51Z
1 votes
以这种方式执行函数是不可能的。
要解决此问题,您可以将函数放在shell脚本中,并从find调用它
# dosomething.sh
dosomething () {
echo "doing something with $1"
}
dosomething $1
现在用它来查找:
find . -exec dosomething.sh {} \;
codaddict answered 2019-05-05T18:50:31Z
1 votes
将该函数放在一个单独的文件中,并获得find来执行它。
Shell函数是它们定义的shell的内部函数; find将永远无法看到它们。
Angus answered 2019-05-05T18:51:05Z
1 votes
我找到了最简单的方法,在单个do中重复两个命令
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
edib answered 2019-05-05T18:51:32Z
0 votes
不直接,没有。 查找是在单独的进程中执行,而不是在shell中执行。
创建一个shell脚本,它与您的函数执行相同的工作,并找到可以-exec。
Laurence Gonsalves answered 2019-05-05T18:52:06Z
-4 votes
我会完全避免使用-exec。 为什么不用xargs?
find . -name
Barry answered 2019-05-05T18:52:33Z