使用bash重命名文件,命令说明

时间:2011-10-16 11:33:25

标签: bash find

关注此问题Recursively rename files using find and sed我自己找到了使用find重命名文件的解决方案,但我无法完全理解最后一部分

find . -name '*_test.rb' -exec bash -c 'echo mv $1 ${1/test.rb/spec.rb}' _ {} \;

任何人都可以解释字符“_ {}”的含义吗?我想这是从环境中映射的一些排序参数,但是......

欢迎提供一些澄清。

1 个答案:

答案 0 :(得分:1)

-exec command ;

字符串`{}'被正在处理的当前文件名替换。 请考虑以下事项:

% find . -type f
./file1
./file2
./file3
./file4
./file5
% find . -type f -exec sh -c 'printf "arg -> %s\n" "$0"' {} \;
arg -> ./file1
arg -> ./file2
arg -> ./file3
arg -> ./file4
arg -> ./file5

但是在这里我们为找到的每个文件执行sh -c ...。 另请注意,文件名将作为 $ 0 (不是 $ 1 )传递给shell。

如果我们想要优化代码,只要我们的命令一次接受多个参数进行处理,我们就可以使用类似的东西:

% find . -type f -exec sh -c 'printf "arg -> %s\n" "$@"' {} +
arg -> ./file2
arg -> ./file3
arg -> ./file4
arg -> ./file5

请注意{} +语法(vs. {} \;)。从查找手册页:

-exec command {} +
          This variant of the -exec action runs the specified command on the selected files, but the command line
          is built by appending each selected file name at the end; the total number of invocations of  the  com-
          mand  will  be  much less than the number of matched files.  The command line is built in much the same
          way that xargs builds its command lines.

但是正如您所观察到的那样,第一个文件丢失了(因为 $ @ 包含除$ 0之外的所有参数)。这就是为什么我们需要手动设置$ 0,以便正确处理所有参数:

% find . -type f -exec sh -c 'printf "arg -> %s\n" "$@"' put_whatever_you_want_here {} +
arg -> ./file1
arg -> ./file2
arg -> ./file3
arg -> ./file4
arg -> ./file5

在某些情况下,您可能需要将 $ 0 设置为有意义的内容。