PowerShell中复制文件夹时排除指定子文件夹的实现方法
PowerShell复制文件夹并排除指定子文件夹/文件的正确实现
嘿,作为PowerShell新手遇到这个复制排除的问题太正常了——原生Copy-Item和Get-ChildItem的组合在递归排除场景里确实有不少坑,我来帮你修正并解释清楚~
首先先说说你原代码里的几个问题:
- 你把
Copy-Item的-Destination写成了$from,这会把文件复制回原路径,完全搞反了,应该是$to Get-ChildItem -Exclude在递归时只会排除顶层名称匹配的项,子文件夹里的目标文件夹(比如某个子目录下的.git)不会被排除- 管道传递对象时,直接写
Copy-Item $_.fullname的语法不对,PowerShell管道里的对象需要通过ForEach-Object或者让Cmdlet直接接收管道输入来处理
下面给你两种可靠的实现方式:
方法1:用Robocopy(推荐,更稳定高效)
Robocopy是Windows自带的专门用于文件复制的工具,处理排除、递归复制场景比PowerShell原生Cmdlet靠谱得多,语法也更直接:
$from = 'C:\erp\github\bliss_' $to = 'C:\erp\websites\bitesize' $excludeFolders = @(".git","DHTMLX","mflasite","nbproject") $excludeFiles = @(".gitignore") # /E:复制所有子文件夹(包括空文件夹) # /XD:排除指定文件夹 # /XF:排除指定文件 # /R:3 /W:5:遇到文件锁定时重试3次,每次等待5秒 robocopy $from $to /E /XD $excludeFolders /XF $excludeFiles /R:3 /W:5
方法2:PowerShell原生Cmdlet实现
如果你不想用外部工具,也可以通过过滤管道对象来实现,核心是检查每个项的完整路径是否包含要排除的文件夹:
$from = 'C:\erp\github\bliss_' $to = 'C:\erp\websites\bitesize' $excludeFolders = @(".git","DHTMLX","mflasite","nbproject") $excludeFiles = @(".gitignore") Get-ChildItem -Path $from -Recurse | Where-Object { # 检查当前项的完整路径是否包含任何要排除的文件夹(正则精确匹配避免误判) $folderMatch = $excludeFolders | ForEach-Object { $_.FullName -match "\\$([regex]::Escape($_))\\" } | Where-Object { $_ } $isExcludedFolder = [bool]$folderMatch # 检查当前项是否是要排除的文件 $isExcludedFile = $excludeFiles -contains $_.Name # 只保留不被排除的项 -not $isExcludedFolder -and -not $isExcludedFile } | Copy-Item -Destination { # 动态替换源路径前缀为目标路径,保持原目录结构 $_.FullName.Replace($from, $to) } -Force
这里用Where-Object过滤掉所有在排除列表里的文件夹和文件,再通过脚本块给Copy-Item生成对应的目标路径,确保复制后目录结构和源目录一致。
内容的提问来源于stack exchange,提问作者Cheviwa
相关产品推荐
相关产品推荐

