PowerShell Copy-Logs函数通配符使用报错问题求助
解决Copy-Logs函数通配符路径报错问题
问题现象
编写的Copy-Logs函数在指定完整路径(如C:\WINDOWS\logs\Software\)时可正常运行,但使用通配符路径(如C:\WINDOWS\logs\Software\ado*)复制日志时,会报错:
WARNING: Failed to copy 'C:\WINDOWS\logs\Software\ado*': Illegal characters in path.
问题原因
- 直接将带通配符的路径传给
Copy-Item的Path参数并配合FromSession时,远程端无法正确解析通配符;且Split-Path $log -Leaf会把通配符*当作目标文件名的一部分,而Windows路径不允许包含*字符,导致路径非法。 - 原逻辑未先在远程会话中解析通配符、获取实际存在的文件/文件夹路径,直接尝试复制带通配符的路径,引发错误。
解决方案
修改函数逻辑,在远程会话中先解析通配符路径,获取匹配的实际路径后再逐个复制;同时修正目标路径生成逻辑,避免将通配符带入目标路径。
修改后的完整函数代码:
function Copy-Logs { [CmdletBinding()] param ( [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, HelpMessage="Specify the name(s) of the computer to run the SCCM actions on, separated by commas ','")] [string[]]$TargetComputerName, [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, HelpMessage="Specify the path(s) of logs.")] [SupportsWildcards()] [string[]]$TargetLogsPaths, [Parameter(Mandatory=$false, HelpMessage="Specify the folder name for destination.")] [ValidateNotNullOrEmpty()] [string]$DestName = "logs", [Parameter(Mandatory=$false, HelpMessage="Specify the Error Action on Copy Item")] [ValidateNotNullOrEmpty()] [ValidateSet("Continue", "SilentlyContinue", "Stop")] [string]$ActionOnError = "Stop", [Parameter(Mandatory=$false, HelpMessage="Specifies whether to include verbose output.")] [Switch]$WriteVerbose, [Parameter(Mandatory=$false, HelpMessage="Specify if the function should create a new folder each time it's run.")] [switch]$NewFolder, [Parameter(Mandatory=$false, HelpMessage="Specify the domain controller to use.")] [string]$TargetDomainController = ".?.?" ) # Convert TargetComputerName to an array if it's a string if (-not $TargetComputerName -is [array]) { $TargetComputerName = $TargetComputerName -split "," } # Convert TargetLogsPaths to an array if it's a string if (-not $TargetLogsPaths -is [array]) { $TargetLogsPaths = $TargetLogsPaths -split '\s*,\s*' -split '\s+' } # Gets current user into variable for DestFolder $CurrentUser = [System.Environment]::UserName # Loop through each computer name and copy the specified logs foreach($ComputerName in $TargetComputerName) { $DateFormat = (Get-Date).ToString('dd-MM-yyyy hh-mm-ss') $HostDate = $ComputerName + ' - ' + $DateFormat $DestFolder = Join-Path "C:\Temp\$CurrentUser" (Join-Path -Path $HostDate -ChildPath $DestName) if ($NewFolder -or (-not(Test-Path $DestFolder))) { New-Item -ItemType "directory" -Path $DestFolder -Force | Out-Null } # Create PSSession $PC = $ComputerName + $TargetDomainController $Session = New-PSSession -ComputerName $PC –UseSSL foreach ($logPattern in $TargetLogsPaths) { # 在远程会话中解析通配符路径,获取实际存在的文件 $remotePaths = Invoke-Command -Session $Session -ScriptBlock { param($pattern) Get-ChildItem -Path $pattern -Recurse -File | Select-Object -ExpandProperty FullName } -ArgumentList $logPattern if (-not $remotePaths) { Write-Warning "No files matched pattern '$logPattern' on computer '$ComputerName'" continue } foreach ($remotePath in $remotePaths) { # 保留远程文件的相对目录结构 $rootDir = Split-Path $logPattern -Parent $relativePath = $remotePath -replace [regex]::Escape($rootDir), '' $relativePath = $relativePath.TrimStart('\') $DestFile = Join-Path $DestFolder $relativePath # 创建目标父目录(如果不存在) $destDir = Split-Path $DestFile -Parent if (-not (Test-Path $destDir)) { New-Item -ItemType Directory -Path $destDir -Force | Out-Null } $copyParams = @{ Path = $remotePath Destination = $DestFile FromSession = $Session ErrorAction = $ActionOnError Verbose = $WriteVerbose } try { Copy-Item @copyParams -PassThru | ForEach-Object { Write-Progress -Activity "Copying File from $ComputerName" -Status $_.Name -PercentComplete (($_.BytesTransferred / $_.TotalBytes) * 100) } } catch { Write-Warning "Failed to copy '$remotePath': $_" } } } # Close PSSession Remove-PSSession $Session } }
关键修改点
- 修正
ActionOnError参数类型:原参数为string[],但Copy-Item的ErrorAction只接受单个字符串值,改为string类型。 - 在远程会话中用
Get-ChildItem解析通配符路径,获取实际存在的文件路径,避免直接复制带通配符的路径。 - 保留远程文件的相对目录结构,确保复制后的文件层级与远程一致。
- 自动创建目标文件的父目录,避免因目录不存在导致复制失败。
内容的提问来源于stack exchange,提问作者Matovina Igor
相关产品推荐
相关产品推荐

