如何在不覆盖重复文件名的情况下递归复制文件?

时间:2015-10-31 17:39:06

标签: bash shell find rename cp

假设我的文件嵌套在具有可能重复文件名的子目录中。我想将所有文件复制到一个新目录,但防止覆盖并保留文件名(主要是)。

以下有效,因为它会覆盖重复的文件名:

find /SourceDir/. -type f -exec cp -pv \{\} /DestDir/ \;

添加noclobbercp -n)也无济于事,因为刚跳过重复项。

当前文件结构:

SourceDir
--SubdirA
----File1.gif
---- ...
----File1000.jpg
--SubdirB
----File1.gif
---- ...
----File1000.png
...
--SubdirZ
----SubdirAA
------File1.sh
------ ...
------File1000.jpg

所需的文件结构:

DestDir
--File1.gif
--File1_1.gif   <-- original name was `File1.gif` but this already existed
--File2.jpg
--File2.gif     <-- `File2.jpg` already exists, but not `File2.gif`
--File3.gif
--File3_1.gif
--File4.jpg
--File4_1.jpg
--File4_2.jpg   <-- original name was `File4.jpg`, but `File4_1.jpg` already existed too.
-- ...
--File1000.png

想要重命名每个文件。而且我不想给那些我需要复制的人任意哈希。你推荐什么?

我在Mac上,所以Linux命令都是合理的游戏。

1 个答案:

答案 0 :(得分:1)

这是一个解决方案。

#!/bin/bash

SourceDir=".";
DestDir="../dest";

cd ${SourceDir}
find .  -type f |
while read x
do
  bn=`basename $x`;
  if [ -f "${DestDir}/$bn" ]
  then
    for i in {1..9999}
    do
        if [ ! -f "${DestDir}/${bn%.*}_${i}.${bn##*.}" ]
        then
            echo "Next free file extension is no $i";
            bn="${DestDir}/${bn%.*}_${i}.${bn##*.}"
            break;
        fi
    done
  fi
  echo "copy file $x to ${DestDir}/$bn";
  cp -p "$x" "${DestDir}/$bn";
 done

如果适合您,请告诉我。