我在另一个目录的子目录中有许多图像,我想将它们复制到一个目录中,以便所有图像都集中在一个地方。
经过一番搜索,我找到并修改了一些内容来创建此命令:
find . -name "z*.jpg" -exec cp '{}' ~/Extracted/ \;
这似乎有效,但是我发现同名的图像会被覆盖,所以我这样做了:
find . -name "z*.jpg" -exec cp -n '{}' ~/Extracted/ \;
但现在同名的图像会被忽略。
有什么办法可以做到这一点,以便复制每个图像并重命名同名图像?
答案1
GNUcp(1)
有一个备份选项:
cp --backup SOURCE [SOURCE...] [DESTINATION]
这具有以下效果,可以通过其他选项进行控制,如手册页的cp(1)
:
--backup[=CONTROL] make a backup of each existing destination file -b like --backup but does not accept an argument -S, --suffix=SUFFIX override the usual backup suffix
备份后缀为
~
,除非使用--suffix
或 进行设置SIMPLE_BACKUP_SUFFIX
。版本控制方法可以通过选项--backup
或VERSION_CONTROL
环境变量进行选择。以下是值:
none
,off
:从不进行备份(即使--backup
给出了)numbered
,t
:进行编号备份existing
,nil
:如果存在编号备份,则使用编号,否则使用简单simple
,never
:始终进行简单备份
例子
cp --backup=existing --suffix=.orig ~/Music/* ~/Videos
这会将所有文件复制到~/Music
。~/Videos
如果目标中存在同名文件,则通过.orig
在其名称后附加 来重命名该文件作为备份。如果存在与备份同名的文件,则通过附加 来重命名备份(.1
如果备份也存在),.2
依此类推。只有这样,源文件才会复制到目标。
如果要递归复制子目录中的文件,请使用-R
:
cp -R --backup=existing --suffix=.orig ~/Music ~/Videos
答案2
您的问题实际上是找到一个cp
变体,如果目标文件已经存在,则以不同的名称创建它。我不知道有这样的工具,但是,自己实现并不难:
cp -vn "$1" "$2"/ || cp -vn "$1" "$2"/"${1##*/}"~"$(md5sum "$1" | cut -f1 -d' ')"
如果失败,此脚本将cp
再次调用,将校验和附加到文件名中。缺陷:如果出现第三个同名文件,它将覆盖第二个文件如果它们相同。
假设上述脚本被调用saveCopy
并存储在父工作目录中,则以下内容有效:
$ find . -name 'z*.jpg' -exec ./saveCopy {} /tmp/Extracted/ \;
./a/z1.jpg -> /tmp/Extracted/z1.jpg
./a/z2.jpg -> /tmp/Extracted/z2.jpg
./a/z3.jpg -> /tmp/Extracted/z3.jpg
/tmp/Extracted/z3.jpg not overwritten
./b/z3.jpg -> /tmp/Extracted//z3.jpg~d41d8cd98f00b204e9800998ecf8427e
./b/z4.jpg -> /tmp/Extracted/z4.jpg
请注意,该脚本仅适用于单个输入文件,并且目标为目录!它当然可以改进 ;-)
答案3
在 Catalina 上运行的 GNU cp 的自制版本似乎存在一个错误,当它复制到包含大量(几千个)文件的目录并使用 --backup 重命名文件时,会导致它挂起。通过减少目标目录中的文件数量解决了这个问题。例如,对于 1000 个文件,它按预期工作。