在PowerShell中递归地将一组文件从一个目录复制到另一个目录

Posted

技术标签:

【中文标题】在PowerShell中递归地将一组文件从一个目录复制到另一个目录【英文标题】:Recursively copy a set of files from one directory to another in PowerShell 【发布时间】:2014-11-07 03:34:41 【问题描述】:

我正在尝试将所有*.csproj.user 文件从C:\Code\Trunk 递归复制到C:\Code\F2

例如:

C:\Code\Trunk\SomeProject\Blah\Blah.csproj.user

将被复制到:

C:\Code\F2\SomeProject\Blah\Blah.csproj.user

我目前的尝试是:

复制项目 C:\Code\Trunk -Filter *.csproj.user -Destination C:\Code\F2 -Recurse -WhatIf

但是我得到:

如果:对目标“项目”执行“复制目录”操作: C:\Code\Trunk 目的地:C:\Code\F2\Trunk"。

首先,它想将它们全部放在一个名为F2\Trunk 的新文件夹中,这是错误的。其次,它没有列出任何文件。应该有大约 10 个文件需要复制。

该命令的正确语法是什么?谢谢!

更新:

好吧,这似乎与C:\Code\F2 已经存在这一事实有关。如果我尝试将文件复制到不存在 的目的地,它会起作用。

我想覆盖目标中任何现有的.csproj.user 文件。

【问题讨论】:

关于创建新文件夹的部分是一个错误,已记录在here。 【参考方案1】:

以前见过这个,我不知道为什么 PowerShell 似乎无法正确处理(恕我直言)。我会做的比较麻烦,但它确实有效。

$Source = 'C:\Code\Trunk'
$Files = '*.csproj.user'
$Dest = 'C:\Code\F2'
Get-ChildItem $Source -Filter $Files -Recurse | ForEach
    $Path = ($_.DirectoryName + "\") -Replace [Regex]::Escape($Source), $Dest
    If(!(Test-Path $Path))New-Item -ItemType Directory -Path $Path -Force | Out-Null
    Copy-Item $_.FullName -Destination $Path -Force

【讨论】:

我认为如果您将参数-LiteralPath 用于Copy-Item 命令,您可以删除整个正则表达式 这似乎只从每个子文件夹中复制一个文件【参考方案2】:

答案 1 看起来不错,出于我的目的,我改为 Move-Item。但是我发现在它递归遍历的每个文件夹中,它只移动了第一个文件。下面是我的完整脚本,其中还包括一些将 doc 文件转换为 pdf 的内容:

$Source = 'C:\Users\sgrody\Desktop\NSPM-Vol1'
$MoveFiles = '*.PDF'
$Dest = 'C:\Users\sgrody\Desktop\MedPassPDF'
$Folders = Get-ChildItem $Source -Directory -Recurse 


ForEach ($Folder in $Folders)

    $wdFormatPDF = 17
    $word = New-Object -ComObject word.application
    $word.visible = $false
    $folderpath = "$($Folder.FullName)\*"
    $fileTypes = "*.docx","*doc"
    Get-ChildItem -path $folderpath -include $fileTypes |
    foreach-object 
    
     $path =  ($_.fullname).substring(0,($_.FullName).lastindexOf("."))
     "Converting $path to pdf ..."
     $doc = $word.documents.open($_.fullname)
     $doc.saveas([ref] $path, [ref]$wdFormatPDF)
     $doc.close()
    
    $word.Quit()


Get-ChildItem $Source -Filter $MoveFiles -Recurse | ForEach
    $Path = ($_.DirectoryName + "\") -Replace [Regex]::Escape($Source), $Dest
    If(!(Test-Path $Path))New-Item -ItemType Directory -Path $Path -Force | Out-Null
    Move-Item $_.FullName -Destination $Path -Force
    

【讨论】:

【参考方案3】:

你们把这件事搞得极其复杂,其实很简单:

Copy-Item C:\Code\Trunk -Filter *.csproj.user -Destination C:\Code\F2 -Recurse

将复制目录,在 F2 中创建一个“Trunk”目录。如果您想避免创建*** Trunk 文件夹,您必须停止告诉 PowerShell 复制它:

Get-ChildItem C:\Code\Trunk | Copy-Item -Destination C:\Code\F2 -Recurse -filter *.csproj.user

【讨论】:

没有人会想到第一种方法是“告诉”它复制文件夹,因为“复制”是“复制项”的别名,而 DOS 中的“复制”没有如果我没记错的话,不是这样工作的。因此,许多人对此感到困惑和复杂。 对我来说,这会将所有内容展平并将所有内容复制到一个文件夹中 @Dan 不幸的是,Copy-Item 有一个,嗯,错误(已被禁止“破坏”旧脚本):如果要创建目标目录,可以使用第一个命令(只是复制项),如果它已经存在,那是你需要第二种语法的时候。 供将来参考:Rejected Edit 标题为“第一个表单无需复制根源文件夹即可工作,只需添加“*”,它只会复制其中的项目”建议更改最后一个Copy-Item C:\Code\Trunk\* -Filter *.csproj.user -Destination C:\Code\F2 -Recurse 的代码行:此编辑旨在解决帖子的作者,作为编辑没有任何意义。它应该写成评论或答案。 @yoyo 是的,我们使用 -filter 只是因为复制一个特定的扩展是原始请求...【参考方案4】:

虽然投票最多的答案对单一文件类型完全有效,但如果您需要复制多种文件类型,还有一个更有用的功能,称为 robocopy 正是为此目的,使用更简单

robocopy C:\Code\Trunk C:\Code\F2 *.cs *.xaml *.csproj *.appxmanifest /s

【讨论】:

我不得不使用 Robocopy,因为 Copy-Item 在较长的文件路径上出错【参考方案5】:

我尝试了 Jaykul 的答案,但它对我不起作用。我必须按如下方式对其进行更改才能使其正常工作。我还在它工作之前创建了 C:\Code\F2 文件夹。

Get-ChildItem C:\Code\Trunk -Recurse -filter *.csproj.user | Copy -Destination C:\Code\F2

【讨论】:

正是我需要的。但必须在“递归”之前添加连字符【参考方案6】:

最近我不得不替换几个子文件夹中存在的文件,我做了如下。

foreach($file in (Get-ChildItem File_you_want_to_be_copied.txt -Recurse)) $target=$file.directoryname; Copy-Item -path C:\Source_Path\File_you_want_to_be_copied.txt -Destination $target 

【讨论】:

以上是关于在PowerShell中递归地将一组文件从一个目录复制到另一个目录的主要内容,如果未能解决你的问题,请参考以下文章

如何将一组 powershell 命令转换为可以在需要时运行的脚本?

如何递归地将目录复制到另一个目录并仅替换未更改的文件?

如何使用 Powershell 从文件中递归地抓取电子邮件地址?

我需要将一组文件从其原始位置复制到一个新文件夹

如果文件不匹配,则递归地将一个目录复制到另一个目录

如何使用PowerShell递归搜索目录中的所有文件,包括隐藏目录中的隐藏文件?