【问题标题】:Copy-item Files in Folders and subfolders in the same directory structure of source server using PowerShell使用PowerShell复制源服务器同一目录结构中的文件夹和子文件夹中的项目文件
【发布时间】:2013-07-24 10:41:44
【问题描述】:

我正在努力让下面的脚本工作以正确结构(作为源服务器)复制文件夹和子文件夹中的文件。

比方说,下面提到了一些文件夹:

主文件夹:文件 aaa、文件 bbb

子文件夹a:文件1、文件2、文件3

子文件夹 b:文件 4、文件 5、文件 6

使用的脚本:

Get-ChildItem -Path \\Server1\Test -recurse | ForEach-Object {
Copy-Item -LiteralPath $_.FullName -Destination \\server2\test |
Get-Acl -Path $_.FullName | Set-Acl -Path "\\server2\test\$(Split-Path -Path $_.FullName -Leaf)"

}

输出: 文件aaa,文件bbb

子文件夹a(空文件夹)

子文件夹 b(空文件夹)

文件 1、文件 2、文件 3、文件 4、文件 5、文件 6。

我希望将文件复制到它们各自的文件夹(如源文件夹)。非常感谢任何进一步的帮助。

【问题讨论】:

  • 如果您想复制所有内容,Kevin_ 的回答应该可以。如果您需要过滤输入,请参阅stackoverflow.com/questions/17788208/…
  • @Kevin_ 在 powershell 中使用 robocopy 的完整示例?

标签: powershell powershell-2.0 powershell-3.0


【解决方案1】:

这可以通过使用 Copy-Item 来完成。无需使用 Get-Childitem。我觉得你只是想多了。

Copy-Item -Path C:\MyFolder -Destination \\Server\MyFolder -recurse -Force

我刚刚对其进行了测试,它对我有用。

编辑: 包括来自 cmets 的建议

# Add wildcard to source folder to ensure consistent behavior
Copy-Item -Path $sourceFolder\* -Destination $targetFolder -Recurse

【讨论】:

  • 我发现如果您多次运行此命令,它的行为会发生变化。第一次,它将所有内容复制到 \\Server\MyFolder。第二次及以后,它会将所有内容复制到 \\Server\MyFolder\MyFolder
  • @thecodefish 我也注意到了这一点,但只有在目标目录不存在时才会发生。使用 New-Item -ItemType 目录 -Path $target -Force | Out-Null 将解决这个问题。 -Force 开关只会在目录不存在时创建目录,并且 Out-Null 不会污染您的输出。
  • 也适用于Copy-Item **/*.txt -Destination C:/destination等模式匹配
  • @thecodefish 旧帖,但这个问题仍然相关。如果将通配符添加到-Path,它将以-Destination 结尾(而不是\\Server\MyFolder\MyFolder)。我最终得到了Copy-Item "$PathToCopy\*" -Destination "$Destination" -Recurse
  • 我的目录结构看起来像这样:./web.config, ./bin/*, ./dll/* ...我在Copy-Item -Path "$sourceFolder\*" -Destination $targetFolder -Recurse 看到的问题是它看起来获取 $sourceFolder 中子目录下的所有内容(在我的情况下为 dll 和 bin),并将其与从 sourceFolder 根目录复制的所有其他文件一起放在 $targetFolder 的根目录下。通过在执行递归复制之前创建 $targetFolder 也修复了此行为。微软:这是不明智或不理智的行为。
【解决方案2】:

如果您想将相同的内容从源镜像到目标,请尝试关注。

function CopyFilesToFolder ($fromFolder, $toFolder) {
    $childItems = Get-ChildItem $fromFolder
    $childItems | ForEach-Object {
         Copy-Item -Path $_.FullName -Destination $toFolder -Recurse -Force
    }
}

测试:

CopyFilesToFolder "C:\temp\q" "c:\temp\w"

【讨论】:

    【解决方案3】:

    有一次我找到了这个脚本,这个复制文件夹和文件,并在目标中保持源的相同结构,你可以用这个做一些尝试。

    # Find the source files
    $sourceDir="X:\sourceFolder"
    
    # Set the target file
    $targetDir="Y:\Destfolder\"
    Get-ChildItem $sourceDir -Include *.* -Recurse |  foreach {
    
        # Remove the original  root folder
        $split = $_.Fullname  -split '\\'
        $DestFile =  $split[1..($split.Length - 1)] -join '\' 
    
        # Build the new  destination file path
        $DestFile = $targetDir+$DestFile
    
        # Move-Item won't  create the folder structure so we have to 
        # create a blank file  and then overwrite it
        $null = New-Item -Path  $DestFile -Type File -Force
        Move-Item -Path  $_.FullName -Destination $DestFile -Force
    }
    

    【讨论】:

      【解决方案4】:

      我在最流行的答案(过度思考)上遇到了麻烦。它将 AFolder 放在 \Server\MyFolder\AFolder 中,我想要 AFolder 的内容以及 MyFolder 下面的内容。这不起作用。

      Copy-Item -Verbose -Path C:\MyFolder\AFolder -Destination \\Server\MyFolder -recurse -Force
      

      另外我需要过滤并且只复制 *.config 文件。

      这不起作用,使用“\*”,因为它没有递归

      Copy-Item -Verbose -Path C:\MyFolder\AFolder\* -Filter *.config -Destination \\Server\MyFolder -recurse -Force
      

      我最终删除了路径字符串的开头,以获取相对于我递归位置的 childPath。这适用于有问题的用例,并且存在许多子目录,而其他一些解决方案则没有。

      Get-Childitem -Path "$($sourcePath)/**/*.config" -Recurse | 
      ForEach-Object {
        $childPath = "$_".substring($sourcePath.length+1)
        $dest = "$($destPath)\$($childPath)" #this puts a \ between dest and child path
        Copy-Item -Verbose -Path $_ -Destination $dest -Force   
      }
      

      【讨论】:

        【解决方案5】:

        我想要一个解决方案来复制在特定日期和时间之后修改的文件,这意味着我不需要使用通过过滤器管道传输的 Get-ChildItem。以下是我想出的:

        $SourceFolder = "C:\Users\RCoode\Documents\Visual Studio 2010\Projects\MyProject"
        $ArchiveFolder = "J:\Temp\Robin\Deploy\MyProject"
        $ChangesStarted = New-Object System.DateTime(2013,10,16,11,0,0)
        $IncludeFiles = ("*.vb","*.cs","*.aspx","*.js","*.css")
        
        Get-ChildItem $SourceFolder -Recurse -Include $IncludeFiles | Where-Object {$_.LastWriteTime -gt $ChangesStarted} | ForEach-Object {
            $PathArray = $_.FullName.Replace($SourceFolder,"").ToString().Split('\') 
        
            $Folder = $ArchiveFolder
        
            for ($i=1; $i -lt $PathArray.length-1; $i++) {
                $Folder += "\" + $PathArray[$i]
                if (!(Test-Path $Folder)) {
                    New-Item -ItemType directory -Path $Folder
                }
            }   
            $NewPath = Join-Path $ArchiveFolder $_.FullName.Replace($SourceFolder,"")
        
            Copy-Item $_.FullName -Destination $NewPath  
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-05-02
          • 1970-01-01
          • 2019-10-12
          • 2013-09-04
          • 1970-01-01
          • 1970-01-01
          • 2016-09-04
          相关资源
          最近更新 更多