Copy-Item 是不是应该创建目标目录结构?

Posted

技术标签:

【中文标题】Copy-Item 是不是应该创建目标目录结构?【英文标题】:Should Copy-Item create the destination directory structure?Copy-Item 是否应该创建目标目录结构? 【发布时间】:2011-09-23 01:58:26 【问题描述】:

我正在尝试将文件复制到新位置,同时维护目录结构。

$source = "c:\some\path\to\a\file.txt"
destination = "c:\a\more\different\path\to\the\file.txt"

Copy-Item  $source $destination -Force -Recurse

但我得到了DirectoryNotFoundException

Copy-Item : Could not find a part of the path 'c:\a\more\different\path\to\the\file.txt'

【问题讨论】:

【参考方案1】:

-recurse 选项仅在源为目录时创建目标文件夹结构。当源是文件时,Copy-Item 期望目标是已经存在的文件或目录。您可以通过以下几种方法来解决这个问题。

选项 1:复制目录而不是文件

$source = "c:\some\path\to\a\dir"; $destination = "c:\a\different\dir"
# No -force is required here, -recurse alone will do
Copy-Item $source $destination -Recurse

选项 2:先“触摸”文件,然后覆盖它

$source = "c:\some\path\to\a\file.txt"; $destination = "c:\a\different\file.txt"
# Create the folder structure and empty destination file, similar to
# the Unix 'touch' command
New-Item -ItemType File -Path $destination -Force
Copy-Item $source $destination -Force

【讨论】:

谢谢谢伊。 touch 方法真的很方便,不需要递归遍历文件夹。 有趣的是,“touch”创建了目录和文件,文件是一个单行文件。如果你在记事本中打开文件(不管扩展名是什么)......文件具有〜原始名称全名...作为(文本?)文件的第1行。然后复制项非常高兴所有文件夹都正确存在。谢谢!我已将您的答案扩展为我的问题的答案:***.com/questions/42818014/…【参考方案2】:

或者,从 PS3.0 开始,您可以简单地使用 New-Item 直接创建目标文件夹,而无需创建“虚拟”文件,例如...

New-Item -Type dir \\target\1\2\3\4\5

...无论它已经存在多少,都会愉快地创建 \\target\1\2\3\4\5 结构。

【讨论】:

【参考方案3】:

这是执行此操作的 oneliner。 Split-Path 检索父文件夹,New-Item 创建它,然后 Copy-Item 复制文件。请注意,目标文件将与源文件具有相同的文件名。此外,如果您需要将多个文件复制到与第二个文件相同的文件夹中,这将不起作用,您将收到 An item with the specified name <destination direcory name> already exists 错误。

Copy-Item $source -Destination (New-Item -Path (Split-Path -Path $destination) -Type Directory)

【讨论】:

现有目录的问题可以通过将-Force传递给New-Item cmdlet来解决。【参考方案4】:

我在 Windows 7 的单个文件夹中有文件,我想重命名并复制到不存在的文件夹中。

我使用了以下 PowerShell 脚本,它定义了一个 Copy-New-Item 函数作为 Test-ItemNew-ItemCopy-Item cmdlet 的包装器:

function Copy-New-Item 
  $SourceFilePath = $args[0]
  $DestinationFilePath = $args[1]

  If (-not (Test-Path $DestinationFilePath)) 
    New-Item -ItemType File -Path $DestinationFilePath -Force
   
  Copy-Item -Path $SourceFilePath -Destination $DestinationFilePath


Copy-New-Item schema_mml3_mathml3_rnc schema\mml3\mathml3.rnc
# More of the same...
Copy-New-Item schema_svg11_svg_animation_rnc schema\svg11\svg-animation.rnc
# More of the same...
Copy-New-Item schema_html5_assertions_sch schema\html5\assertions.sch
# More of the same...

(请注意,在这种情况下,源文件名没有文件扩展名。)

如果目标文件路径不存在,函数会在该路径中创建一个空文件,强制在文件路径中创建任何不存在的目录。 (如果Copy-Item 可以自己完成所有这些,我无法从documentation 看到如何做到这一点。)

【讨论】:

【参考方案5】:

它来晚了,但是当我偶然发现这个问题以寻找类似问题的解决方案时,我在其他地方找到的最干净的问题是使用 robocopy 而不是 Copy-Item。我需要将整个文件结构与文件一起复制,这很容易通过

robocopy "sourcefolder" "destinationfolder" "file.txt" /s 

关于robocopy的详细信息:https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/robocopy

【讨论】:

我喜欢这个,因为如果您在变量中捕获它,它会返回一份完整的复制过程报告。 $result = robocopy.exe "sourcefolder" "destinationfolder" "file.txt" /s【参考方案6】:

我一直在挖掘并找到了很多解决这个问题的方法,所有这些都是一些改变,而不仅仅是一个直接的 copy-item 命令。授予它其中一些问题早于 PS 3.0,因此答案没有错,但使用 powershell 3.0,我终于能够使用 -Container 开关来完成此操作。

Copy-Item $from $to -Recurse -Container

这是我运行的测试,没有错误,目标文件夹代表相同的文件夹结构。

New-Item -ItemType dir -Name test_copy
New-Item -ItemType dir -Name test_copy\folder1
New-Item -ItemType file -Name test_copy\folder1\test.txt
#NOTE: with no \ at the end of the destination the file is created in the root of the destination, does not create the folder1 container
#Copy-Item D:\tmp\test_copy\* D:\tmp\test_copy2 -Recurse -Container

#if the destination does not exists this created the matching folder structure and file with no errors
Copy-Item D:\tmp\test_copy\* D:\tmp\test_copy2\ -Recurse -Container

【讨论】:

这不是what -Container does。你对正在发生的事情有错误的推理。 -Recurse 将导致创建目标文件夹。不同的是,当“test_copy2”不存在时,test_copy 的内容将变为(不被复制到)test_copy2。尝试在 test_copy 中创建另一个文件夹,然后在不创建 test_copy2 的情况下执行 copy-item,最终会出错。最后是否使用“\”也无关紧要,-Container 始终为 $true 并且具有此处假设的不同功能。 @papo 我没有理由说它只是对我提供的示例起作用 但是原因在命令中非常重要。如果您在不了解它的工作原理的情况下使用命令,它可能在一种情况下有效,但在另一种情况下会失败。显然你在测试过程中犯了一个错误。我想您在第一次测试后没有删除目标测试文件夹。你考虑过我的反应并再次测试了吗?你明白吗,如果 -Container 默认为 $true,(docs 是错误的)你是否使用它都没有区别。您只能通过以下方式将其关闭:-Container:$false。尝试一下。不要只是在论坛上发布假设,人们正在从中学习。【参考方案7】:

当前的答案都无法解决Copy-Item 引发的Could not find a part of the path 错误。经过一些研究和测试,我发现如果Destination 路径越过260 character Windows path length limit,就会引发此错误。

我的意思是:如果您提供Copy-ItemDestination 参数的路径,并且您复制的任何文件在复制到Destination 文件夹时将超过260 个字符的限制,@987654328 @ 将引发 Could not find a part of the path 错误。

解决方法是缩短您的 Destination 路径,或缩短/展平您尝试复制的源目录中的文件夹结构。

【讨论】:

【参考方案8】:

可能会有帮助:

$source = 'c:\some\path\to\a\file.txt'
$dest = 'c:\a\more\different\path\to\the\file.txt'
$dest_dir = 'c:\a\more\different\path\to\the\'

[System.IO.Directory]::CreateDirectory($dest_dir);
if(-not [System.IO.File]::Exists($dest))

    [System.IO.File]::Copy($source,$dest);

【讨论】:

以上是关于Copy-Item 是不是应该创建目标目录结构?的主要内容,如果未能解决你的问题,请参考以下文章

Powershell Copy-Item 目标不明确

如何修复“value null Copy-Item Powershell”错误

创建一个目录结构(带有嵌套路由 + 漂亮的 url,...)

Linux文件目录结构实验

Copy-Item 用于使用凭据将文件从本地复制到远程服务器

《分布式微服务电商》专题(十四)-电商项目商品类目后台页面访问