在 Linux 中 find -exec 一个 shell 函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4321456/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 23:56:07  来源:igfitidea点击:

find -exec a shell function in Linux?

linuxbashshellfindbsd

提问by alxndr

Is there a way to get findto execute a function I define in the shell? For example:

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

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

The result of that is:

结果是:

find: dosomething: No such file or directory

Is there a way to get find's -execto see dosomething?

有没有办法让find-execdosomething

采纳答案by Adam Rosenfield

Since only the shell knows how to run shell functions, you have to run a shell to run a function. You also need to mark your function for export with export -f, otherwise the subshell won't inherit them:

由于只有 shell 知道如何运行 shell 函数,因此您必须运行 shell 才能运行函数。您还需要使用 标记导出函数export -f,否则子shell 将不会继承它们:

export -f dosomething
find . -exec bash -c 'dosomething "
# dosomething.sh
dosomething () {
  echo "doing something with "
}
dosomething 
"' {} \;

回答by Laurence Gonsalves

Not directly, no. Find is executing in a separate process, not in your shell.

不直接,不。Find 在单独的进程中执行,而不是在您的 shell 中执行。

Create a shell script that does the same job as your function and find can -execthat.

创建一个与您的函数完成相同工作的 shell 脚本,然后找到-exec它。

回答by codaddict

It is not possible to executable a functionthat way.

不可能以这种方式执行函数

To overcome this you can place your function in a shell script and call that from find

为了克服这个问题,您可以将您的函数放在一个 shell 脚本中并从 find

find . -exec dosomething.sh {} \;

Now use it in find as:

现在在 find 中使用它:

find . | while read file; do dosomething "$file"; done

回答by Angus

Put the function in a separate file and get findto execute that.

将该函数放在一个单独的文件中并开始find执行。

Shell functions are internal to the shell they're defined in; findwill never be able to see them.

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

回答by Jac

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

回答by Wagner

Add quotes in {}as shown below:

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

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

This corrects any error due to special characters returned by find, for example files with parentheses in their name.

这将纠正由 返回的特殊字符引起的任何错误find,例如名称中带有括号的文件。

回答by Barry

I would avoid using -execaltogether. Why not use xargs?

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

#!/bin/bash

if [ !  == "" ] ; then
   echo "doing something with "
   exit 0
fi

find . -exec 
find . -print0 | while IFS= read -r -d '' file; do dosomething "$file"; done
{} \; exit 0

回答by Mike Maready

Have the script call itself, passing each item found as an argument:

让脚本调用自身,将找到的每个项目作为参数传递:

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

When you run the script by itself, it finds what you are looking for and calls itself passing each find result as the argument. When the script is run with an argument, it executes the commands on the argument and then exits.

当您自己运行脚本时,它会找到您要查找的内容并调用自己,将每个查找结果作为参数传递。当脚本使用参数运行时,它会执行参数上的命令,然后退出。

回答by pajamian

Jak's answer above is great but has a couple of pitfalls that are easily overcome:

上面 Jak 的回答很好,但有几个容易克服的陷阱:

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

This uses null as a delimiter instead of a linefeed, so filenames with linefeeds will work. It also uses the -rflag which disables backslash escaping, without it backslashes in filenames won't work. It also clears IFSso that potential trailing whitespaces in names are not discarded.

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

回答by Dominik

Processing results in bulk

批量处理结果

For increased efficiency, many people use xargsto process results in bulk, but it is very dangerous. Because of that there was an alternate method introduced into findthat executes results in bulk.

为了提高效率,很多人xargs习惯于批量处理结果,但这是非常危险的。因此,引入了一种替代方法find来批量执行结果。

Note though that this method might come with some caveats like for example a requirement in POSIX-findto have {}at the end of the command.

不过,请注意,这种方法可能附带像例如在POSIX-要求一些注意事项find{}在命令结束。

##代码##

findwill pass many results as arguments to a single call of bashand the for-loop iterates through those arguments, executing the function dosomethingon each one of those.

find将许多结果作为参数传递给单个调用,bash并且for-loop 迭代这些参数,dosomething对每个参数执行函数。

The above solution starts arguments at $1, which is why there is a _(which represents $0).

上面的解决方案从 开始参数$1,这就是为什么有 a _(代表$0)。

Processing results one by one

一一处理结果

In the same way, I think that the accepted top answer should be corrected to be

同样,我认为应将公认的最佳答案更正为

##代码##

This is not only more sane, because arguments should always start at $1, but also using $0could lead to unexpected behavior if the filename returned by findhas special meaning to the shell.

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