`find -exec` 里面这个奇怪的语法是什么? [英] What is this strange syntax inside `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.
在以下示例中,函数 foo
将针对每个 find
结果调用.
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:
find
动作-exec
允许您对找到的文件和目录应用命令.
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
、$2
...) 从参数 $1
开始.
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
使用 查找 .-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屋!