复制文件而不覆盖

Posted

技术标签:

【中文标题】复制文件而不覆盖【英文标题】:Copy files without overwrite 【发布时间】:2011-05-12 20:15:24 【问题描述】:

我只是似乎无法在命令行上找到一种方法说“将所有文件从目录A复制到目录B,但是如果文件已经存在于目录B中,请不要覆盖它,无论哪个文件较新,不要提示我。”

我经历过复制、移动、xcopy 和 robocopy,我能得到的最接近的是,你可以告诉 robocopy“将 A 复制到 B,但不要用旧文件覆盖新文件”,但这并没有为我工作。我查看了 xxcopy,但放弃了它,因为我不想让第三方依赖于 Visual Studio 构建后事件,这将需要其他 SVN 用户安装该工具才能进行构建。

我想在 Visual Studio 2010 的构建后事件中添加一个命令行,以便从 T4 模板为新的 EF 模型对象生成的文件分发到它们所属的项目文件夹,但为现有对象重新生成的文件不会覆盖可能已编辑的目标文件。

由于T4模板重新生成,源文件总是较新,我不认为可靠地使用“较新”开关。

我对那些我可以使用的项目使用部分类,但我生成的其他东西不能使用部分类(例如,生成默认的 EditorTemplate 或 DisplayTemplate *.ascx 文件)。

有人解决过类似的问题吗?

【问题讨论】:

你熟悉cmd.exefor命令吗?如果没有,我建议你运行 for /? 并使用它。 【参考方案1】:
For %F In ("C:\From\*.*") Do If Not Exist "C:\To\%~nxF" Copy "%F" "C:\To\%~nxF"

【讨论】:

这对我有用,但我必须使用百分之二的符号而不是一个,因为我是从批处理文件而不是命令行中运行它。我用 %%F 替换了 %F 的实例,用 %%~nxF 替换了 %~nxF 的实例。 ~nx in %~nxF 到底是什么意思? @stu,它只是说对于~nxF,变量F变成了文件名和扩展名。 是的,非常有效,给我文件名+扩展名,不带路径——这是您在目标文件夹中进行测试并指定目标文件名所需要的。关键是 %F 包含路径,你不希望它在那里。【参考方案2】:

Robocopy或“Robust File Copy”,是一个命令行目录复制命令。从 Windows NT 4.0 开始,它已作为 Windows 资源工具包的一部分提供,并作为 Windows Vista、Windows 7 和 Windows Server 2008 的标准功能引入。

   robocopy c:\Sourcepath c:\Destpath /E /XC /XN /XO

详细说明(使用 Hydrargyrum、HailGallaxar 和 Andy Schmidt 的答案):

/E 使 Robocopy 递归复制子目录, 包括空的。 /XC 排除现有文件 相同的时间戳,但不同 文件大小。 Robocopy 通常会覆盖这些。 /XN 排除现有文件较新 比目标中的副本 目录。 Robocopy 正常 覆盖那些。 /XO 不包括 现有文件较旧 比目标中的副本 目录。 Robocopy 正常 覆盖那些。

排除 Changed、Older 和 Newer 类后,Robocopy 完全按照原始发布者的要求执行 - 无需加载脚本环境。

参考:Technet、Wikipedia 下载地址:Microsoft Download Link(链接最后验证日期为 2016 年 3 月 30 日)

【讨论】:

“排除”是指“跳过”还是“删除/删除”? @Andre Terra:跳过,通常。如果您使用 /MIR 标志,它可能会删除它们。我还没有测试过。 使用 /MIR,确实会删除源中不存在的文件。但是当同时使用 /XN 和 /XO 时,两个地方都存在的文件会被简单地跳过(不确定是否检查了大小)。这非常适合我需要复制应用程序的新版本或旧版本但应用程序使用的库的 dateModified 标记不正确但文件名本身包含其版本号的情况。 是否需要包含/e?如果您改用/s 会怎样?我不想要一堆空的子文件夹。 /S 而不是 /E 完全没问题。它按照文档中列出的方式执行(不包括 emtpy 子目录)。【参考方案3】:

这里是批处理文件的形式:

@echo off
set source=%1
set dest=%2
for %%f in (%source%\*) do if not exist "%dest%\%%~nxf" copy "%%f" "%dest%\%%~nxf"

【讨论】:

【参考方案4】:

贝利撒留的解决方案很好。

详细说明这个稍微简洁的答案:

/E 使 Robocopy 递归复制子目录, 包括空的。 /XC 排除现有文件 相同的时间戳,但不同 文件大小。 Robocopy 通常会覆盖这些。 /XN 排除现有文件较新 比源中的副本 目录。 Robocopy 正常 覆盖那些。 /XO 不包括 现有文件较旧 比源中的副本 目录。 Robocopy 正常 覆盖那些。

排除 Changed、Older 和 Newer 类后,Robocopy 完全按照原始发布者的要求执行 - 无需加载脚本环境。

【讨论】:

【参考方案5】:

对于尚未安装的系统,可以在此处下载 Robocopy。 (即 Windows Server 2003。)

http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=17657 (安装无需重启)

请记住将路径设置为 robocopy exe。您可以通过右键单击“我的电脑”>“属性”>“高级”>“环境变量”来执行此操作,然后找到路径系统变量并将其添加到末尾:“;C:\Program Files\Windows Resource Kits\Tools”或任何你想要的地方安装它。确保保留已经存在的路径变量字符串,并附加附加路径。

一旦设置了路径,您就可以运行 belisarius 建议的命令。它工作得很好。

【讨论】:

【参考方案6】:

我只是想从我自己的测试中澄清一些事情。

@Hydrargyrum 写道:

/XN 排除比源目录中的副本更新的现有文件。 Robocopy 通常会覆盖这些。 /XO 排除比源目录中的副本更旧的现有文件。 Robocopy 通常会覆盖这些内容。

这实际上是倒退的。 XN 会“排除较新的”文件,但会排除比 destination 目录中的副本更新的文件。 XO 会“排除旧的”,但它会排除比 destination 目录中的副本更旧的文件。

当然要像往常一样进行自己的测试。

【讨论】:

这是对原始问题的回答,还是对别人回答的评论? 在撰写原始问题的答案时,Hydrargyrum 的答案是 +25 票,还是对其他人的答案的评论?【参考方案7】:

你可以试试这个:

echo n | copy /-y <SOURCE> <DESTINATION>

-y 只是在覆盖之前进行提示,我们可以将 n 传递给所有这些问题。所以这本质上只是复制不存在的文件。 :)

【讨论】:

非常简单。 为什么我们只用管道一次就可以回答所有问题? 太棒了,我选择了这个选项。在考虑管道之前,我搜索了一个我认为我缺少的参数,然后我遇到了这个页面。尝试这个解决方案时,我注意到在管道时,复制显然启用了 /Y 参数,所以这就是必须添加 /-Y 的原因。 @phuclv 似乎copy /-y 只是在标准输入用完输入后自动假定否。您可以省略第一个显式的n,或者将&lt; nul 插入其中,同样的事情也会发生。【参考方案8】:

使用 xcopy 有一种奇怪的方法:

echo nnnnnnnnnnn | xcopy /-y source target

只需包含与您要复制的文件一样多的 n,它就会回答所有覆盖问题的 n。

【讨论】:

关于copy,见this answer,特别是@mwfearnley 评论:copy /-y 自动假设n 一旦标准输入用尽,所以你可以例如echo n 只用一次,它仍然有效。【参考方案9】:

它不会让我直接评论不正确的消息 - 但让我警告大家,与之前的消息中发布的内容相比,/XN 和 /XO 选项的定义是反向的。

Exclude Older/Newer files 选项与 RoboCopy 日志中显示的信息一致:RoboCopy 将遍历 SOURCE,然后报告 SOURCE 中的每个文件是否比目标中的文件“旧”或“新”。

因此,/XO 将排除 OLDER SOURCE 文件(这很直观),而不是此处声称的“比源更旧”。

如果您只想复制新的或更改的源文件,但避免替换较新的目标文件,那么 /XO 是正确的选择。

【讨论】:

【参考方案10】:

一种简单的方法是使用 /MIR 选项来镜像这两个目录。基本上它只会将新文件复制到目的地。在下一个命令中,将源和目标替换为您的文件夹的路径,该脚本将搜索具有任何扩展名的任何文件。

robocopy <source directory> <destination directory> *.* /MIR

【讨论】:

【参考方案11】:

这对我有用。我用它把文件“添加”到另一个驱动器上,没有覆盖。

批处理文件:robocopy-missingfiles.bat

@echo off
echo Copying 
echo      "%1"
echo   to "%2"
echo.
echo Press Cntr+C to abort
Pause
echo.
@echo on
robocopy %1 %2 /Xo /XN /XC /J /SL /S /MT:8 /R:1 /W:1 /V /DCOPY:DAT /ETA /COPY:DATO /FFT /A-:SH /XD $RECYCLE.BIN "System Volume Information"

示例:

robocopy-missingfiles.bat f:\Working-folder\ E:\Backup-folder\

在实施前进行测试。

【讨论】:

【参考方案12】:
robocopy src dst /MIR /XX

/XX :排除“eXtra”文件和目录(存在于目标但不存在源)。这将防止从目标中删除任何内容。 (这是默认设置)

【讨论】:

以上是关于复制文件而不覆盖的主要内容,如果未能解决你的问题,请参考以下文章

sh 在源路径中查找文件并将其复制到目标。该命令将覆盖目标文件夹中的文件而不询问。

Linux复制文件到某路径并重命名

Linux复制文件到某路径并重命名

cmd,如何让xcopy命令在复制时不提示覆盖?

cp -复制文件

LinuxShellcp 用法详解