【问题标题】:Powershell 2 copy-item which creates a folder if doesn't existPowershell 2复制项,如果不存在则创建一个文件夹
【发布时间】:2010-04-23 00:50:08
【问题描述】:
$from = "\\something\1 XLS\2010_04_22\*"
$to =  "c:\out\1 XLS\2010_04_22\"
copy-item $from $to -Recurse 

如果c:\out\1 XLS\2010_04_22\ 确实存在,则此方法有效。如果 c:\out\1 XLS\2010_04_22\ 不存在,是否可以使用单个命令创建它?

【问题讨论】:

    标签: powershell copy powershell-2.0


    【解决方案1】:

    在 PowerShell 3 及更高版本中,我将 Copy-Item 与 New-Item 结合使用。

    copy-item -Path $file -Destination (new-item -type directory -force ("C:\Folder\sub\sub\" + $newSub)) -force -ea 0
    

    我没有在第 2 版中尝试过。

    【讨论】:

    • 这非常适合本地复制谢谢!但在使用-ToSession 命令时不会:'(
    【解决方案2】:

    是的,添加-Force 参数。

    copy-item $from $to -Recurse -Force
    

    【讨论】:

    • PowerShell 是那么容易知道它:)
    • 这适用于整个目录,但是如果我只是复制单个文件(这样我可以获得状态)怎么办?当 c:\test2 不存在时,如何将 c:\test1\file.txt 复制到 c:\test2\file.txt?这就是我真正需要知道的。谢谢,加里
    • 我遇到了同样的问题并通过首先调用 New-Item 解决了它:New-Item -Force $toCopy-Item -Force $from $to
    【解决方案3】:
    $file | Copy-Item -Destination (New-Item -Force -Type Directory -Path $directoryName)
    

    【讨论】:

      【解决方案4】:

      这是一个对我有用的例子。我有一个文本文件中大约 500 个特定文件的列表,包含在大约 100 个不同的文件夹中,我应该将其复制到备份位置,以防以后需要这些文件。文本文件包含完整路径和文件名,每行一个。就我而言,我想从每个文件名中去掉驱动器号和第一个子文件夹名。我想将所有这些文件复制到我指定的另一个根目标文件夹下的类似文件夹结构中。我希望其他用户觉得这对您有所帮助。

      # Copy list of files (full path + file name) in a txt file to a new destination, creating folder structure for each file before copy
      $rootDestFolder = "F:\DestinationFolderName"
      $sourceFiles = Get-Content C:\temp\filelist.txt
      foreach($sourceFile in $sourceFiles){
          $filesplit = $sourceFile.split("\")
          $splitcount = $filesplit.count
          # This example strips the drive letter & first folder ( ex: E:\Subfolder\ ) but appends the rest of the path to the rootDestFolder
          $destFile = $rootDestFolder + "\" + $($($sourceFile.split("\")[2..$splitcount]) -join "\")
          # Output List of source and dest 
          Write-Host ""
          Write-Host "===$sourceFile===" -ForegroundColor Green
          Write-Host "+++$destFile+++"
          # Create path and file, if they do not already exist
          $destPath = Split-Path $destFile
          If(!(Test-Path $destPath)) { New-Item $destPath -Type Directory }
          If(!(Test-Path $destFile)) { Copy-Item $sourceFile $destFile }
      }
      

      【讨论】:

        【解决方案5】:
          $filelist | % {
            $file = $_
            mkdir -force (Split-Path $dest) | Out-Null
            cp $file $dest
          } 
        

        【讨论】:

          【解决方案6】:
          function Copy-File ([System.String] $sourceFile, [System.String] $destinationFile, [Switch] $overWrite) {
          
              if ($sourceFile -notlike "filesystem::*") {
                  $sourceFile = "filesystem::$sourceFile" 
              }
          
              if ($destinationFile -notlike "filesystem::*") {
                  $destinationFile = "filesystem::$destinationFile" 
              }
          
              $destinationFolder = $destinationFile.Replace($destinationFile.Split("\")[-1],"")
          
              if (!(Test-Path -path $destinationFolder)) {
                  New-Item $destinationFolder -Type Directory
              }
          
              try {
                  Copy-Item -Path $sourceFile -Destination $destinationFile -Recurse -Force
                  Return $true 
              } catch [System.IO.IOException] {
                  # If overwrite enabled, then delete the item from the destination, and try again:
                  if ($overWrite) {
                      try {
                          Remove-Item -Path $destinationFile -Recurse -Force        
                          Copy-Item -Path $sourceFile -Destination $destinationFile -Recurse -Force 
                          Return $true
                      } catch {
                          Write-Error -Message "[Copy-File] Overwrite error occurred!`n$_" -ErrorAction SilentlyContinue
                          #$PSCmdlet.WriteError($Global:Error[0])
                          Return $false
                      }
                  } else {
                      Write-Error -Message "[Copy-File] File already exists!" -ErrorAction SilentlyContinue
                      #$PSCmdlet.WriteError($Global:Error[0])
                      Return $false
                  }
              } catch {
                  Write-Error -Message "[Copy-File] File move failed!`n$_" -ErrorAction SilentlyContinue
                  #$PSCmdlet.WriteError($Global:Error[0]) 
                  Return $false
              } 
          }
          

          【讨论】:

          • 欢迎来到 Stack Overflow!感谢您提供此代码 sn-p,它可能会提供一些即时帮助。一个正确的解释would greatly improve 其教育价值通过展示为什么这是一个很好的解决问题的方法,并将使它对未来有类似但不相同的问题的读者更有用。请edit您的答案添加解释,并说明适用的限制和假设。
          【解决方案7】:

          我在这里绊倒了两次,最后一次是一个独特的情况,即使我放弃使用 copy-item 我想发布我使用的解决方案。

          只有包含完整路径的文件的列表,并且在大多数情况下,这些文件没有扩展名。 -Recurse -Force 选项对我不起作用,所以我放弃了 copy-item 函数并使用 xcopy 退回到下面的内容,因为我仍然想保持它为一个衬里。最初我与 Robocopy 绑定,但它显然是在寻找文件扩展名,因为我的许多人没有扩展名,所以它认为它是一个目录。

          $filelist = @("C:\Somepath\test\location\here\file","C:\Somepath\test\location\here2\file2")
          
          $filelist | % { echo f | xcopy $_  $($_.Replace("somepath", "somepath_NEW")) }
          

          希望它可以帮助某人。

          【讨论】:

            【解决方案8】:

            我最喜欢的是使用 .Net [IO.DirectoryInfo] 类,它负责一些逻辑。我实际上将它用于许多类似的脚本挑战。它有一个 .Create() 方法,可以创建不存在的目录,即使存在也不会出错。

            由于这仍然是一个两步问题,我使用 foreach 别名来保持简单。对于单个文件:

            [IO.DirectoryInfo]$to |% {$_.create(); cp $from $_}
            

            就您的多文件/目录匹配而言,我会使用 RoboCopy 而不是 xcopy。从您的 from 中删除“*”,然后使用:

            RoboCopy.exe $from $to *
            

            您仍然可以添加 /r(递归)、/e(包括空的递归),还有 50 个其他有用的开关。

            编辑: 回顾一下,它很简洁,但如果您不经常使用该代码,则可读性不强。通常我把它分成两部分,像这样:

            ([IO.DirectoryInfo]$to).Create()
            cp $from $to
            

            另外,DirectoryInfoFileInfo 的 Parent 属性的类型,所以如果你的 $to 是一个文件,你可以使用它们一起:

            ([IO.FileInfo]$to).Parent.Create()
            cp $from $to
            

            【讨论】:

              【解决方案9】:

              在 PowerShell 2.0 中,仍然无法获取 Copy-Item cmdlet 来创建目标文件夹,您需要如下代码:

              $destinationFolder = "C:\My Stuff\Subdir"
              
              if (!(Test-Path -path $destinationFolder)) {New-Item $destinationFolder -Type Directory}
              Copy-Item "\\server1\Upgrade.exe" -Destination $destinationFolder
              

              如果您在 Copy-Item 中使用 -Recurse,它将在目标中创建源结构的所有子文件夹,但不会创建实际的目标文件夹,即使使用 -Force。

              【讨论】:

              • 感谢您的观察。我得到了一些不一致的复制操作;有时它复制了一个子文件夹,有时它没有。在确保目标文件夹存在后,这种不一致就消失了。
              • 我也遇到目标文件夹不存在时的错误行为
              • 谢谢。这就是我一直在寻找的答案。糟糕的是没有切换到创建目标文件夹。
              【解决方案10】:

              我修改了@FrinkTheBrave 的答案以创建子目录并解析相对路径:

              $src_root = Resolve-Path("./source/path/")
              $target_root = Resolve-Path("./target/path/")
              $glob_filter = "*.*"
              Get-ChildItem -path $src_root -filter $glob_filter -recurse | 
                ForEach-Object {
                      $target_filename=($_.FullName -replace [regex]::escape($src_root),$target_root) 
                      $target_path=Split-Path $target_filename
                      if (!(Test-Path -Path $target_path)) {
                          New-Item $target_path -ItemType Directory
                      }
                      Copy-Item $_.FullName -destination $target_filename
                  }
              

              【讨论】:

                猜你喜欢
                • 2017-06-28
                • 1970-01-01
                • 2011-01-19
                • 2013-09-18
                • 2013-06-24
                • 2014-09-07
                • 1970-01-01
                • 2020-07-12
                相关资源
                最近更新 更多