【问题标题】:does exec mv command used with find deletes the files?与 find 一起使用的 exec mv 命令会删除文件吗?
【发布时间】:2021-12-25 07:11:58
【问题描述】:

我想用一个命令重命名文件夹中的几个文件,而不是一个一个地重命名它们。

我有一个名为 /u0x/XMLs 的文件夹,其中大约有 500 个文件夹。每个文件夹都有一个名为PROCESSED_ADI.XML 的文件。我想将所有这些文件重命名为ADI.XML

我尝试将find-exec mv 一起使用:

XMLs]$ find . -name "*.XML" -exec mv {} ADI.XML \;

执行命令后,所有文件都已从文件夹中删除或从那里移动,我不确定。有人能解释一下出了什么问题吗?有什么办法可以检索文件吗?

【问题讨论】:

    标签: linux bash shell find mv


    【解决方案1】:

    执行命令后,所有文件都已从文件夹中删除或从那里移动,我不确定

    您正在重命名文件,但目标或重命名的文件具有不同的位置,它是您运行 find 命令的当前位置/路径。

    如果您的find 支持,您可以使用-execdir

    find . -name "*.XML" -execdir mv -v {} ADI.XML \;
    

    这是execdir的定义

     -execdir command {} +
                  Like -exec, but the specified command is run from the subdirectory containing the matched file, which is not normally the directory in which you started  find.   As  with
                  -exec,  the  {} should be quoted if find is being invoked from a shell.  This a much more secure method for invoking commands, as it avoids race conditions during resolu-
                  tion of the paths to the matched files.  As with the -exec action, the `+' form of -execdir will build a command line to process more than one matched file, but any given
                  invocation  of  command  will  only list files that exist in the same subdirectory.  If you use this option, you must ensure that your $PATH environment variable does not
                  reference `.'; otherwise, an attacker can run any commands they like by leaving an appropriately-named file in a directory in which  you  will  run  -execdir.   The  same
                  applies  to  having entries in $PATH which are empty or which are not absolute directory names.  If any invocation with the `+' form returns a non-zero value as exit sta-
                  tus, then find returns a non-zero exit status.  If find encounters an error, this can sometimes cause an immediate exit, so some pending commands may not be run  at  all.
                  The result of the action depends on whether the + or the ; variant is being used; -execdir command {} + always returns true, while -execdir command {} ; returns true only
                  if command returns 0.
    

    这里有一个关于什么/为什么你的文件被删除删除的演示。

    让我们在任何地方创建一个虚拟目录和文件,但这里我们将在 /tmp 中创建它们

    cd  /tmp
    

    让我们创建目录和文件。

    mkdir -p u0x/XMLs/folder_{1..10} && touch u0x/XMLs/folder_{1..10}/PROCESSED_ADI.XML
    

    现在使用tree 命令检查在这些目录中创建的内容。

    tree u0x/
    

    输出

    u0x/
    └── XMLs
        ├── folder_1
        │   └── PROCESSED_ADI.XML
        ├── folder_10
        │   └── PROCESSED_ADI.XML
        ├── folder_2
        │   └── PROCESSED_ADI.XML
        ├── folder_3
        │   └── PROCESSED_ADI.XML
        ├── folder_4
        │   └── PROCESSED_ADI.XML
        ├── folder_5
        │   └── PROCESSED_ADI.XML
        ├── folder_6
        │   └── PROCESSED_ADI.XML
        ├── folder_7
        │   └── PROCESSED_ADI.XML
        ├── folder_8
        │   └── PROCESSED_ADI.XML
        └── folder_9
            └── PROCESSED_ADI.XML
    
    11 directories, 10 files
    

    现在我们执行您的find 命令,但使用-v 标志/选项。

    find u0x/ -name "*.XML" -exec mv -v {} ADI.XML \;
    

    输出

    renamed './XMLs/folder_2/PROCESSED_ADI.XML' -> 'ADI.XML'
    renamed './XMLs/folder_9/PROCESSED_ADI.XML' -> 'ADI.XML'
    renamed './XMLs/folder_7/PROCESSED_ADI.XML' -> 'ADI.XML'
    renamed './XMLs/folder_10/PROCESSED_ADI.XML' -> 'ADI.XML'
    renamed './XMLs/folder_6/PROCESSED_ADI.XML' -> 'ADI.XML'
    renamed './XMLs/folder_3/PROCESSED_ADI.XML' -> 'ADI.XML'
    renamed './XMLs/folder_8/PROCESSED_ADI.XML' -> 'ADI.XML'
    renamed './XMLs/folder_1/PROCESSED_ADI.XML' -> 'ADI.XML'
    renamed './XMLs/folder_4/PROCESSED_ADI.XML' -> 'ADI.XML'
    renamed './XMLs/folder_5/PROCESSED_ADI.XML' -> 'ADI.XML'
    

    现在使用tree 命令检查文件发生了什么。

    tree u0x/
    

    输出

    u0x/
    ├── ADI.XML
    └── XMLs
        ├── folder_1
        ├── folder_10
        ├── folder_2
        ├── folder_3
        ├── folder_4
        ├── folder_5
        ├── folder_6
        ├── folder_7
        ├── folder_8
        └── folder_9
    
    11 directories, 1 file
    

    现在,如果您仔细查看tree 的上述输出 所有 PROCESSED_ADI.XML 已从其位置/文件夹中消失,但在父目录/ 中有一个 ADI.XML文件夹u0x 就像@Gordon Davidsonmentioned All 一样,xml(只要文件以 .xml 结尾)文件已被移动到一个位置并再次被覆盖同样,现在您只有一个名为的文件。 ADI.XML


    使用-execdir 将获得您正在寻找的预期输出。


    如果使用了-execdirtree 命令的输出应该是:

    tree u0x/
    
    u0x/
    └── XMLs
        ├── folder_1
        │   └── ADI.XML
        ├── folder_10
        │   └── ADI.XML
        ├── folder_2
        │   └── ADI.XML
        ├── folder_3
        │   └── ADI.XML
        ├── folder_4
        │   └── ADI.XML
        ├── folder_5
        │   └── ADI.XML
        ├── folder_6
        │   └── ADI.XML
        ├── folder_7
        │   └── ADI.XML
        ├── folder_8
        │   └── ADI.XML
        └── folder_9
            └── ADI.XML
    
    11 directories, 10 files
    

    【讨论】:

    • 感谢您的洞察力。这里的问题是,在我执行命令 find 之后。 -name ".XML" -exec mv {} ADI.XML \;从/u0x/Xmls/,我想重命名的文件已经从子文件夹中消失了。所以现在当我运行命令 find 。 -name ".XML" -execdir mv -v {} ADI.XML \;它什么也不返回,因为“find . -name "*.XML" 没有找到任何文件
    • @SaNu,是的,因为它已从其位置/路径移动到您运行 find 命令的当前位置/路径。
    • @SaNu 不幸的是,我认为除了其中一个之外,所有这些都已被删除。它试图将它们全部移动到同一个地方,但它移动的每一个都替换了前一个(删除它)。这就是为什么我总是建议使用mv -imv -n 进行任何类型的批量/自动移动/重命名操作。你有备份吗?
    • @Gordon Davisson 不幸的是我没有备份,我认为你所说的确实发生了。
    • 当我检查该文件夹中没有任何 .XML 文件时执行了 find 命令,看起来 find 命令从 subfloders 中找到的所有文件都已被删除。
    【解决方案2】:

    首先,不要使用通配符。即使使用-execdir,您也会创建一种情况,即目录中的所有.XML 文件都将被该目录中的最后一个匹配项覆盖。

    find . -type f -name 'PROCESSED_ADI.XML' -exec sh -c 'for i do echo mv "${i}" "$(dirname "$i")/ADI.XML"; done' _ {} +
    

    运行这个,作为试运行。如果看起来没问题,请删除 echo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-31
      • 2018-12-28
      • 2011-08-02
      • 2016-03-15
      • 1970-01-01
      • 1970-01-01
      • 2017-08-08
      相关资源
      最近更新 更多