如何复制某些文件(没有文件夹层次结构),但不要覆盖现有文件?

Vla*_*kov 11 powershell copy file overwrite flatten

我需要将所有*.doc文件(但不是名称匹配的文件夹*.doc)从网络文件夹\\server\source(包括所有嵌套文件夹中的文件)复制到本地文件夹C:\destination而不保留嵌套文件夹层次结构(即所有文件应直接进入,C:\destination并且不应嵌套文件夹创建于C:\destination).如果有多个文件具有相同名称的不同子文件夹\\server\source,则只应复制第一个文件 ,然后不要覆盖 - 之后发现的所有冲突文件都应该被跳过(可能有很多这样的情况,跳过的文件不应该通过网络传输,否则需要花费太多时间).这是我尝试在PowerShell中实现它:

cp \\server\source\* -Recurse -Include *.doc -Container:$false -Destination C:\destination
Run Code Online (Sandbox Code Playgroud)

此命令至少存在两个问题:

  • 它复制名称匹配的文件夹*.doc.
  • 如果名称冲突,以后找到的任何文件都将通过网络传输并覆盖前一个文件.

你能建议如何解决这些问题吗?
使用实现copy,xcopy,robocopy,cscript或者*.bat,*.cmd也欢迎.
本地操作系统是Windows 8,文件系统是NTFS.

Gra*_*old 15

我会先生成文件列表,然后在列表中进行验证.

像这样的东西:

$srcdir = "\\server\source\";
$destdir = "C:\destination\";
$files = (Get-ChildItem $SrcDir -recurse -filter *.doc | where-object {-not ($_.PSIsContainer)});
$files|foreach($_){
    if (!([system.io.file]::Exists($destdir+$_.name))){
                cp $_.Fullname ($destdir+$_.name)
    };
}
Run Code Online (Sandbox Code Playgroud)

因此,用于Get-ChildItem列出与过滤器匹配的源文件夹中的文件,管道输出where-object以删除目录.

然后遍历foreach循环中的每个文件,并使用.NET类的Exists方法检查目标中是否存在文件名(不是Fullname)system.io.file.

如果没有,请仅使用原始文件名(删除原始路径)进行复制.

-whatif在测试时使用副本上的选项,因此它只显示它会做什么,以防结果不是你想要的:-)


Adi*_*bar 7

以前的答案对我来说似乎过于复杂,除非我误解了一些东西.这应该工作:

Get-ChildItem "\\server\source\" *.doc -Recurse | ?{-not ($_.PSIsContainer -or (Test-Path "C:\Destination\$_"))} | Copy-Item -Destination "C:\Destination"
Run Code Online (Sandbox Code Playgroud)

内置命令(复制,xcopy或robocopy)都不会自行完成您想要的操作,但有一个名为xxcopy的实用程序可以在http://www.xxcopy.com上方便地找到.它有许多内置选项,专门用于将目录树展平为单个目录.以下将按您的描述进行:

xxcopy "\\server\source\*.doc" "C:\Destination" /SGFO
Run Code Online (Sandbox Code Playgroud)

但是,xxcopy具有处理重复文件名的各种其他选项,而不仅仅是复制遇到的第一个文件名,例如将源目录名添加到文件名,或者向除第一个之外的所有文件添加顺序数字标识,或者除了最新或最旧之外的所有文件都添加顺序数字标识.有关详细信息,请参阅此页面:http://www.xxcopy.com/xxcopy16.htm

  • 展平层次结构是问题的目标:"不保留嵌套文件夹层次结构(即所有文件应直接进入C:\ destination,并且不应在C:\ destination中创建嵌套文件夹)". (3认同)