find -exec内部的奇怪语法是什么? [英] What is this strange syntax inside `find -exec`?

查看:106
本文介绍了find -exec内部的奇怪语法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我遇到了一个奇怪的bash脚本,该脚本用于从find -exec内部调用自定义bash函数.我已经开发了以下简单的脚本来演示我需要解释的功能.

Recently I've came across a strange bash script, which is used to call a custom bash function from inside find -exec. I've developed following simple script to demonstrate the functionality I need to get explained.

在下面的示例中,将为每个find结果调用函数foo.

In the following example, function foo will be called for each find result.

foo()                                                                                                                                                 
{
    echo "$@"
}
export -f foo

find . -exec bash -c 'foo "$@"' bash {} \;

有人可以解释-exec之后的部分如何解释吗?

Can someone explain how the part after -exec is interpreted?

更新:

为进一步简化此操作,如上所述导出foo后,将对每个find结果执行以下操作(假设有一个名为my_file的文件).

To further simplify this, after exporting foo as above, following gets executed for each find result (assume there is a file named my_file).

bash -c 'foo "$#"' bash my_file

这将产生输出myfile.我不明白这是怎么回事.那里的第二个bash是什么?任何详细的解释,不胜感激.

And this produces the output myfile. I don't understand how this works. What does the second bash does there? Any detailed explanation is appreciated.

(请注意,此问题与find命令无关.也请忽略功能foo的功能,我只想导出一些功能)

(Please note that this question is not about find command. Also please ignore the functionality of function foo, I just wanted to export some function)

推荐答案

要了解,您需要了解4件事:

To understand you need to know 4 things:

  1. find操作-exec允许您在找到的文件和目录上应用命令.

  1. The find action -exec allows you to apply a command on the found files and directories.

-c bash选项记录如下:

BASH(1)
...
OPTIONS
...
       -c        If the -c option is present, then commands are read from
                 the first non-option  argument  command_string.
                 If  there are arguments after the command_string, they
                 are assigned to the positional parameters, starting with $0.

...

If bash is started with the -c option, then $0 is set to the first
argument after the string to be executed, if one is present.
Otherwise, it is set to the filename used to invoke bash, as given
by argument zero.

  • bash中,$@随从参数$1开始的所有位置参数($1$2 ...)扩展.

  • In bash, $@ expands as all positional parameters ($1, $2...) starting at parameter $1.

    bash函数中,位置参数是调用该函数时传递给该函数的参数.

    In a bash function, the positional parameters are the arguments passed to the function when it is called.

    因此,在您的情况下,为找到的每个文件或目录执行的命令为:

    So, in your case, the command executed for each found file or directory is:

    bash -c 'foo "$@"' bash <the-file>
    

    位置参数因此设置为:

    $0 = bash
    $1 = <the-file>
    

    在这种情况下,要求

    bash执行'foo "$@"'.首先将"$@"扩展为"<the-file>".因此,函数foo用一个单独的参数"<the-file>"调用.因此,在功能foo的情况下,位置参数为:

    and bash is asked to execute 'foo "$@"' in this context. "$@" is first expanded as "<the-file>". So, function foo is called with one single argument: "<the-file>". In the context of function foo the positional parameters are thus:

    $1 = "<the-file>"
    

    echo "$@"扩展为echo "<the-file>".

    所有这些仅打印所有找到的文件或目录的名称.几乎就像您有以下任何一种情况一样:

    All this just prints the names of all found files or directories. It is almost as if you had any of:

    find . -exec echo {} \;
    find . -print
    find .
    find
    

    (对于接受最后一个版本的find版本).

    (for find versions that accept the last one).

    几乎就像,因为如果文件或目录名称包含空格,则根据您对find和引号的使用,您将获得不同的结果.因此,如果您打算使用更复杂的foo函数,则应注意引号.例子:

    Almost as if, only, because if file or directory names contain spaces, depending on your use of find and of quotes, you will get different results. So, if you intend to have a more complex foo function, you should pay attention to the quotes. Examples:

    $ touch "filename with spaces" plain
    $ ls -1
    filename with spaces
    plain                                                # 2 files
    $ foo() { echo "$@"; }                               # print arguments
    $ find . -type f
    ./filename with spaces
    ./plain
    $ find . -type f -exec bash -c 'foo "$@"' bash {} \;
    ./filename with spaces
    ./plain
    $ find . -type f -exec bash -c 'foo $@' bash {} \;
    ./filename with spaces
    ./plain
    

    3个find命令显然可以执行相同的操作,但是:

    The 3 find commands apparently do the same but:

    $ bar() { echo $#; }                                 # print number of arguments
    $ wc -w < <(find . -type f)
    4                                                    # 4 words
    $ find . -type f -exec bash -c 'bar "$@"' bash {} \;
    1                                                    # 1 argument
    1                                                    # per file
    $ find . -type f -exec bash -c 'bar $@' bash {} \;
    3                                                    # 3 arguments
    1                                                    # 1 argument
    

    使用find . -type f -exec bash -c 'bar "$@"' bash {} \;,第一个文件名作为一个单独的参数传递给函数bar,而在所有其他情况下,它被视为3个单独的参数.

    With find . -type f -exec bash -c 'bar "$@"' bash {} \;, the first file name is passed to function bar as one single argument, while in all other cases it is considered as 3 separate arguments.

    这篇关于find -exec内部的奇怪语法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆