Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
File 如何复制某些文件(不包含文件夹层次结构),但不覆盖现有文件?_File_Powershell_Copy_Overwrite_Flatten - Fatal编程技术网

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

File 如何复制某些文件(不包含文件夹层次结构),但不覆盖现有文件?,file,powershell,copy,overwrite,flatten,File,Powershell,Copy,Overwrite,Flatten,我需要将所有*.doc文件(但不是名称与*.doc匹配的文件夹)从网络文件夹\\server\source(包括所有嵌套文件夹中的文件)复制到本地文件夹C:\destination,而不保留嵌套文件夹层次结构(即,所有文件应直接进入C:\destination,并且不应在C:\destination中创建嵌套文件夹)。如果从\\server\source的不同子文件夹中有多个同名文件,则只应复制第一个文件,然后再也不覆盖-应跳过以后找到的所有冲突文件(可能有很多这样的情况,跳过的文件不应通过网络

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

cp \\server\source\* -Recurse -Include *.doc -Container:$false -Destination C:\destination
此命令至少有两个问题:

  • 它还复制名称与
    *.doc
    匹配的文件夹
  • 在名称冲突的情况下,稍后找到的任何文件都会通过网络传输并覆盖以前的文件
您能建议如何解决这些问题吗?
也欢迎使用
copy
xcopy
robocopy
cscript
*.bat
*.cmd
实现。

本地操作系统是Windows 8,文件系统是NTFS。

我将首先生成文件列表,并在您查看列表时进行验证

大概是这样的:

$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)
    };
}
因此,使用
getchilditem
列出源文件夹中与过滤器匹配的文件,通过
where object
将目录剥离出来

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

如果没有,复制,只使用原始文件名(删除原始路径)

测试时在副本上使用
-whatif
选项,这样它只显示在结果不是您想要的情况下将执行的操作:-)

第一行读取每个*.doc文件和*.doc?(因此它也考虑Office 2010.docx格式),不包括目录和重复文件。
第二行将每个项目从目标复制到源(文件夹C:\destination必须已经存在)。

一般来说,我建议您将命令拆分为多行,因为这样更容易生成代码(在本例中,第一个任务:获取文件,第二个任务:复制文件)。

前面的答案对我来说似乎过于复杂,除非我有误解。这应该可以:

Get-ChildItem "\\server\source\" *.doc -Recurse | ?{-not ($_.PSIsContainer -or (Test-Path "C:\Destination\$_"))} | Copy-Item -Destination "C:\Destination"
没有任何内置命令(copy、xcopy或robocopy)可以独立完成您想要的任务,但是有一个名为xxcopy的实用程序,可以方便地在上获得。它有许多内置选项,专门用于将目录树展平到单个目录中。以下内容将完成您所描述的操作:

xxcopy "\\server\source\*.doc" "C:\Destination" /SGFO

但是,除了复制遇到的第一个文件名外,xxcopy还有其他多种处理重复文件名的选项,例如将源目录名添加到文件名中,或将顺序数字标识添加到除第一个以外的所有文件名中,或添加到除最新或最旧文件名以外的所有文件名中。有关详细信息,请参阅本页:

为什么在您已经使用foreach有管道吗?为胜利计算属性

Get-ChildItem -Recurse -Path:\\Server\Path -filter:'*.doc' | 
    Where { -not $_.PSIsContainer } |
    Group Name |
    Select @{Name='Path'; Expression={$_.Group[0].FullName}},@{Name='Destination'; Expression={'C:\Destination\{0}' -f $_.Name}} |
    Copy-Item

如果脚本运行两次,预期的行为是什么?它还是应该复制所有内容一次?还是不复制任何内容?@splattedbits目标目录可以假定最初为空。如果此前提条件失败,则脚本行为可能未定义。嗯,我真的不理解这种否决票,除非有人对其表示异议第一行的措辞。这并不是故意的侮辱,我只是觉得已经发布的答案需要经过额外的步骤才能更简单地完成。如果你不牺牲清晰性,简单性和简洁性难道不被认为在编码中更可取吗?无论如何,OP明确表示他欢迎解决方案using copy commands。我提供了关于第三方复制实用程序的信息,该实用程序是专门为完成他想用一个开关完成的任务而定制的。这“没有用”是怎么回事?尝试了您的选项(第一个)-这很好,但它使层次结构扁平化是问题的目标:“不保留嵌套文件夹层次结构(即,所有文件应直接进入C:\destination,并且不应在C:\destination中创建嵌套文件夹)”。抱歉,没有注意到这一点。您的回答是正确的-经过一些修改后对我有帮助。谢谢您没有注意到括号,而不是
[system.io.file]::存在
,您还应该能够使用测试文件
xxcopy "\\server\source\*.doc" "C:\Destination" /SGFO
Get-ChildItem -Recurse -Path:\\Server\Path -filter:'*.doc' | 
    Where { -not $_.PSIsContainer } |
    Group Name |
    Select @{Name='Path'; Expression={$_.Group[0].FullName}},@{Name='Destination'; Expression={'C:\Destination\{0}' -f $_.Name}} |
    Copy-Item