【问题标题】:Using both basename and full path in find -exec在 find -exec 中同时使用基本名称和完整路径
【发布时间】:2013-10-08 05:02:03
【问题描述】:

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

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

提前致谢!

【问题讨论】:

    标签: linux find filenames rename


    【解决方案1】:

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

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

    【讨论】:

    • 这是给我的。
    • @Makkou 的回答很好,并且很好地解释了 POSIX 历史上最令人抓狂的现象之一,但这使得代码更具可读性并解决了一大类案例的问题。但是,记住这些边缘情况的更通用的解决方案真是太好了。
    【解决方案2】:

    要查看执行查找时发生了什么,只需键入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
    

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

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

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

    这里对我拥有的 2 个 xml 文件执行了两次回显,并且由于没有更多的 '{}' 是 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 中执行副本(在 exec 之后添加 shbash 或您最喜欢的 shell)并让 find 将文件名作为 parapeter 传递给它; )

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

    希望这能有所帮助,请执行我的英语。

    【讨论】:

      【解决方案3】:

      试试这样的:

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

      【讨论】:

      • 我真的很喜欢这种方法,但我在 OSX 上得到了find: -printf: unknown primary or operator
      【解决方案4】:

      要获取您使用的基本名称

      basename $your_full_path
      

      在基本名称之前获取该路径

      dirname $your_full_path
      

      【讨论】:

      • 很抱歉要求用勺子喂食,但我如何将其应用于我的 find 实例?
      【解决方案5】:

      你需要结合前两个答案

      我用

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

      第一个答案给出了

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

      或者对于我的尾部命令

      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
      

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

      【讨论】:

        猜你喜欢
        • 2021-06-29
        • 2020-06-10
        • 2020-02-14
        • 1970-01-01
        • 2018-08-13
        • 1970-01-01
        • 2011-11-30
        • 2012-08-04
        相关资源
        最近更新 更多