在find -exec中使用basename和full path

nea*_*lob 7 linux filenames rename find

今天我正在寻找bash脚本世界的冒险.

假设我要将/ home/mine/Pictures的任何子目录中的任何png文件复制到/ home/mine/pngcoppies,并使用find和-exec将其重命名为"copy [basename]".这将要求我在同一个exec命令中使用完整路径名和基名.我的问题是我不知道如何获得基名.(见下文)

find /home/mine -iname "*.png" -exec cp {} /home/mine/pngcoppies/copy{what_do_I_enter_here?} \;
Run Code Online (Sandbox Code Playgroud)

注意:上面的内容实际上并不是我正在做的,但它是问题的一个基本示例,因此使用其他方法实现相同目的的解决方法在这里并不适用.问题基本上是关于find -exec及其对basenames的使用.

提前致谢!

小智 11

要查看执行查找时发生的情况,只需键入set -xv
-x:在执行时打印命令及其参数.
-v:读取shell输入行时打印它们.

这是我有的:

find . -name "*.xml" -exec echo {} \;
Run Code Online (Sandbox Code Playgroud)

给出输出:

./log.xml
./svnLog.xml
Run Code Online (Sandbox Code Playgroud)

当我尝试:

set -xv
find . -name "*.xml" -exec echo {} \;
Run Code Online (Sandbox Code Playgroud)

我明白了:

find . -name "*.xml" -exec echo {} \;
+ find . -name '*.xml' -exec echo '{}' ';'
./log.xml
./svnLog.xml
Run Code Online (Sandbox Code Playgroud)

然后找到执行echo传递找到的文件名而不是litteral: '{}'

但是当你在{}下面添加一些东西时:

find . -name "*.xml" -exec echo something{} \;
+ find . -name '*.xml' -exec echo 'something{}' ';'
something{}
something{}
Run Code Online (Sandbox Code Playgroud)

这里对我所拥有的2个xml文件执行两次echo,并且由于'{}'exec的参数列表不再有,它不会被替换.所以我们找到了echo 'something{}'每个文件.

为了解决这个问题,您可以考虑执行echo传递给它的文件名作为参数,例如:

sh -xvc 'echo sothing/$0' filename
Run Code Online (Sandbox Code Playgroud)

我们已经知道什么是-x-v.-c是从它后面的字符串中获取命令(man sh)

结果是:

sh -xvc 'echo somthing/$0' filename
+ sh -xvc 'echo somthing/$0' filename
echo somthing/$0
+ echo somthing/filename
sothing/filename
Run Code Online (Sandbox Code Playgroud)

我使用' echo somthing/$0'之间'',以便$ 0不会被当前的shell扩展.尝试用"",你会看到$ 0的扩展;)

因此,要回到"问题",查找应格式如下:

find . -name "*.xml" -exec sh -xvc 'echo sothing/$0' {} \;
Run Code Online (Sandbox Code Playgroud)

我们会得到:

find . -name "*.xml" -exec sh -xvc 'echo sothing/$0' {} \;
+ find . -name '*.xml' -exec sh -xvc 'echo sothing/$0' '{}' ';'
echo sothing/$0
+ echo sothing/./log.xml
sothing/./log.xml
echo sothing/$0
+ echo sothing/./svnLog.xml
sothing/./svnLog.xml
Run Code Online (Sandbox Code Playgroud)

我们可以看到,find会执行shell cammand echo sothing/$0传递给它'{}'(由find找到的文件名替换)所以我们得到了所需的echo sothing/./log.xml

set +xv 删除详细模式,我们可以得到:

find . -name "*.xml" -exec sh -c 'echo "cp $0 someWhereElse/$0"' {} \;
cp ./log.xml someWhereElse/./log.xml
cp ./svnLog.xml someWhereElse/./svnLog.xml
Run Code Online (Sandbox Code Playgroud)

所以你的情况,你刚才执行在子壳复印件(添加shbash或者您的EXEC后FAVORIT壳),并让find该文件名作为parapeter传递给它;)

find /home/mine -iname "*.png" -exec sh -c 'cp $0 /home/mine/pngcoppies/copy/$0' {} \;
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助我,并为我的英语执行.


mic*_*ses 9

从man找到:"-execdir primary与-exec primary相同,但实用程序将从保存当前文件的目录执行.替换字符串``{}''的文件名不合格."

find /home/mine -iname "*.png" -execdir cp {} /home/mine/pngcoppies/copy{} \;
Run Code Online (Sandbox Code Playgroud)

  • 这就是适合我的。 (2认同)