在find -exec中使用basename和full path

时间:2013-10-01 21:29:10

标签: linux find filenames rename

今天我正在寻找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?} \;

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

提前致谢!

5 个答案:

答案 0 :(得分:11)

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

这就是我所拥有的:

find . -name "*.xml" -exec echo {} \;

给出输出:

./log.xml
./svnLog.xml

当我尝试时:

set -xv
find . -name "*.xml" -exec echo {} \;

我明白了:

find . -name "*.xml" -exec echo {} \;
+ find . -name '*.xml' -exec echo '{}' ';'
./log.xml
./svnLog.xml

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

但是当您向{}添加内容时,如下所示:

find . -name "*.xml" -exec echo something{} \;
+ find . -name '*.xml' -exec echo 'something{}' ';'
something{}
something{}

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

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

sh -xvc 'echo sothing/$0' filename

我们已经知道-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

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

因此,要回到“问题”,请将格式设置如下:

find . -name "*.xml" -exec sh -xvc 'echo sothing/$0' {} \;

我们会得到:

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

正如我们所知,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

所以在你的情况下,你只需要在子shell中执行副本(添加shbash或者你喜欢exec之后的shell)并让find传递文件名作为它的护照;)

find /home/mine -iname "*.png" -exec sh -c 'cp $0 /home/mine/pngcoppies/copy/$0' {} \;

希望这会有所帮助,并为我的英语执行。

答案 1 :(得分:9)

从男人发现: “-execdir primary与-exec primary相同,但实用程序将从保存当前文件的目录执行。替换字符串”{}“的文件名不合格。”

find /home/mine -iname "*.png" -execdir cp {} /home/mine/pngcoppies/copy{} \;

答案 2 :(得分:1)

尝试这样的事情:

find  /home/mine -iname "*.png" -printf "%P\n " | xargs  -I % -n1 cp %  /home/mine/pngcoppies/copy% 

答案 3 :(得分:0)

要获取您使用的基本名称

basename $your_full_path

在基本名称

之前获取该路径
dirname $your_full_path

答案 4 :(得分:0)

您需要结合前两个答案

我正在使用

将一个目录中的所有内容拖到另一个目录中
find . -type f -exec sh -c 'tail -n 1000 $0 >../tail1000/$0.tail' {} \;

第一个答案给出

cp ./log.xml someWhereElse/./log.xml

或者是我的tail命令

find . -type f -exec sh -c 'tail -n 1000 $0 >../tail1000/$0.tail' {} \;

tail -n 1000 ./filenane > ../tail1000/./filenane.tail

这出乎意料地起作用,但是看起来不是一个不错的路径,我希望在某些情况下,path /./ morepath在某些命令下会执行某些意外操作。

结合答案即可

find . -type f -execdir sh -c 'tail -n 1000 $0 >../tail1000/$0.tail' {} \;

执行

tail -n 1000 filenane > ../tail1000/filenane.tail

并且看起来更有可能给出预期的结果。