【问题标题】: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'

【问题讨论】:

    标签: powershell


    【解决方案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行。然后复制项非常高兴所有文件夹都正确存在。谢谢!我已将您的答案扩展为我的问题的答案:stackoverflow.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);
          }
          

          【讨论】:

            猜你喜欢
            • 2014-06-01
            • 1970-01-01
            • 2019-12-02
            • 1970-01-01
            • 1970-01-01
            • 2016-07-11
            • 1970-01-01
            • 2011-07-01
            • 1970-01-01
            相关资源
            最近更新 更多