移动特定类型的文件并重命名具有相同名称的文件

移动特定类型的文件并重命名具有相同名称的文件

这是我想要实现的目标:

pst使用 readpst 库将文件转换为单独的.eml文件。转换每个文件后pst,我得到了一个嵌套有多个子目录的目录,并且每个目录和子目录都有.eml1..n.

问题是我需要将它们全部放在一个目录中,但是当我尝试像这样移动它们时:

find . -name '*.zip' -exec mv --target-directory='/path/to/outputdir' '{}' +

它找到那些同名的并以以下结尾:

mv: will not overwrite just created 

有谁知道如何将文件移动到一个目录并重命名,以免它们发生冲突?

答案1

GNU 实现cp有一个--backup=[CONTROL]选项,如果目标文件已存在,则创建不同名称的文件。该格式有点难看,因为它使用波浪号(“~”)来分隔备份扩展名。

对于您的情况,一个有用的CONTROL论点可能是numbered

find . -name '*.zip' -exec cp --backup=numbered '{}' '/path/to/outputdir' \;

请注意,由于我不知道 的任何此类选项mv,因此如果您采用此方法,则稍后必须在单独的步骤中删除原始文件。

我在此解决方案中看到的一个问题是,无法区分哪个文件来自哪个目录。编辑:尽管有些人认为这种行为是合适的,并且是浏览器的默认行为,例如,当您多次将同名文件下载到同一目录时。尽管在这种情况下这些“备份”的文件扩展名不同,但它也是编号的。

除了上述之外,您还可以将路径嵌入到每个文件名中,例如将斜杠分隔符更改为下划线。尽管结果信息更丰富,但您可能会得到非常长且丑陋的文件名,并且存在很大的错误空间:

find . -name '*.zip' | while read filePath; do cp "$filePath" '/path/to/outputdir'/"$(echo "$filePath" | sed -e 's#^\\.##' -e 's#/#_#g')"; done

此外,实际上包含下划线的文件看起来会很奇怪,并且如果其文件名的下划线分隔部分以前是否是路径名部分,则可能会产生歧义。

'/path/to/outputdir'请注意,以 开头的命令之间的斜杠字符"$(echo "$filePath" |...非常重要!

第一个表达式是为了避免在搜索树的顶部指定以点字符开头sed时创建隐藏文件。find第二个只是用下划线替换路径分隔符斜杠。

该解决方案的可扩展性也不是很好,因为如果您只想修改查询,您可能必须进行大量更改find,以避免出现严重的结果。例如,如果find查询还包含目录,cp则不会处理这些行。幸运的是,在这种情况下,复制会失败,您甚至会在错误流中收到一条消息。覆盖文件系统上的内容可不是开玩笑!

相关内容