在Linux中查找并复制同名文件到目标文件夹,不要覆盖已有文件。

9

我想要在一个文件夹及其子文件夹中找到并复制所有的*.jpg文件到另一个文件夹中。

我使用以下命令:

find /tempL/6453/ -name "*.jpg" |  xargs  -I  '{}' cp {} /tempL/;

但它会覆盖同名文件。
例如,在/tempL/6453/中,有test(1).jpgtest(2).jpg和文件夹1,在/tempL/6453/1/中,也有相同名称的文件test(1).jpg test(2).jpg
如果我使用上述命令,在/tempL/中只有两个文件test(1).jpgtest(2).jpg,无法将所有文件复制到/tempL/
我想要的是将所有文件复制到/tempL/,当有相同的文件名时,只需将它们重命名即可,如何操作?

cp *.jpg PUT_DESTINATION_PATH - Omid CompSCI
@OmidCompSCI 请仔细阅读问题。诚然,它的措辞可能可以更好些,但很明显OP想要重命名在任何源目录中具有相同名称的文件。您的建议不会重命名也不会递归源子目录。 - kaylum
@kaylum,抱歉我没有完全理解,也不确定递归的含义,但是它不应该使用-r吗? - Omid CompSCI
@OmidCompSCI -r 确实是用于递归目录的。但它只有在源是目录时才有效。*.jpg 不是目录。如果您不理解问题,请先要求澄清。 - kaylum
@kaylum 哦,明白了,谢谢你的澄清。很抱歉我无法回答这个问题,但我期待看到答案! - Omid CompSCI
3个回答

7
我想要的是将所有文件复制到/tempL/,当存在相同文件名时,只需重命名它们即可。如何操作?
1) 如果您不想覆盖已有文件,cp --backup 命令会为现有文件提供备份,并且使用 --suffix 选项,您还可以指定备份所使用的后缀。
2) cp --parents 选项将保留目录结构,即文件夹1中的文件将被复制到新创建的1文件夹中。
3) 如果您想自定义重命名处理过程,则不能仅使用 cp 命令。编写脚本并调用它来处理 find 的结果。

2

安装“GNU并行工具”,然后使用:

find /tempL/6453/ -name "*.jpg" | parallel 'cp {} ./dest-dir/`stat -c%i {}`_{/}'

{/}  ................. gets filename with no full path

我认为使用xargs应该也是可行的,但学习parallel对我来说非常棒,它为我们提供了许多美妙的解决方案。
建议在cp之前使用echo测试您的命令。
"最初的回答": 我认为可以用xargs采用相同的方法,但是学习parallel对我来说很神奇,它给我们提供了很多漂亮的解决方案。我建议在执行命令前使用echo来测试cp

1
也可以尝试使用 --dry-run 而不是 echo。它也适用于像 'seq 10 | parallel 'ls {} || echo Not found {}'` 这样的命令。 - Ole Tange

0
以下是一个经过测试和工作的实现。

型号

#!/bin/bash

find "<SOME_FOLDER_PATH>" -type f "<SOME_FIND_ARG>" -exec sh -c '
    DESTINATION_DIR="<SOME_DESTINY_FOLDER>"
    for FOUND_FILE do
        BASE_NAME=$(basename "$FOUND_FILE")
        if [ -f "$DESTINATION_DIR/$BASE_NAME" ]; then
            cp "$FOUND_FILE" "$DESTINATION_DIR/$BASE_NAME-$(uuidgen | cut -d "-" -f 2)"
        else
            cp "$FOUND_FILE" "$DESTINATION_DIR/$BASE_NAME"
        fi
    done
' bash {} +

例子

#!/bin/bash

find "/some/folder/path/" -type f -iname "*some_find_arg*" -exec sh -c '
    DESTINATION_DIR="/some/destiny/folder"
    for FOUND_FILE do
        BASE_NAME=$(basename "$FOUND_FILE")
        if [ -f "$DESTINATION_DIR/$BASE_NAME" ]; then
            cp "$FOUND_FILE" "$DESTINATION_DIR/$BASE_NAME-$(uuidgen | cut -d "-" -f 2)"
        else
            cp "$FOUND_FILE" "$DESTINATION_DIR/$BASE_NAME"
        fi
    done
' bash {} +

额外内容:删除重复文件...

示例

cd "/some/destiny/folder"
fdupes -rdN ./

# r - recursive
# d - preserve first file, delete other dupes
# N - run silently (no prompt)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接