PowerShell中灵活处理Destination参数路径的最优方案咨询
针对你遇到的Destination参数输入不统一的问题,这里提供一个通用的PowerShell函数,可处理所有你列出的输入场景,同时解决文件名合法性验证的问题。
核心解析函数
function Resolve-DestinationPath { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string]$Path, # 源文件路径 [Parameter(Mandatory=$true)] [string]$Destination # 用户输入的目标值 ) # 解析源文件的完整路径、文件名、扩展名 $sourceFullPath = Resolve-Path -Path $Path -ErrorAction Stop $sourceFileName = [System.IO.Path]::GetFileName($sourceFullPath.Path) $sourceExtension = [System.IO.Path]::GetExtension($sourceFullPath.Path) # 解析用户输入的目标路径(不检查是否存在) $destResolved = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Destination) $isDirectory = $false # 判断输入是否为目录:结尾带分隔符,或实际存在且是目录 if ($Destination.EndsWith([System.IO.Path]::DirectorySeparatorChar) -or $Destination.EndsWith([System.IO.Path]::AltDirectorySeparatorChar)) { $isDirectory = $true } elseif (Test-Path -Path $destResolved -PathType Container) { $isDirectory = $true } else { # 无扩展名则自动继承源文件扩展名 $destExtension = [System.IO.Path]::GetExtension($destResolved) if ([string]::IsNullOrEmpty($destExtension)) { $destFileName = [System.IO.Path]::GetFileName($destResolved) $destDirectory = [System.IO.Path]::GetDirectoryName($destResolved) $destResolved = [System.IO.Path]::Combine($destDirectory, "$destFileName$sourceExtension") } } # 如果是目录,拼接源文件名 if ($isDirectory) { $destResolved = [System.IO.Path]::Combine($destResolved, $sourceFileName) } # 验证文件名合法性(排除系统不允许的字符) $invalidChars = [System.IO.Path]::GetInvalidFileNameChars() $destFileName = [System.IO.Path]::GetFileName($destResolved) if ($destFileName.IndexOfAny($invalidChars) -ge 0) { throw "目标文件名包含非法字符:$destFileName" } return $destResolved }
场景处理逻辑说明
- 仅提供带扩展名的文件名:自动结合当前工作目录生成完整路径
- 仅提供不带扩展名的文件名:自动添加源文件的扩展名,结合当前工作目录生成完整路径
- 仅提供目录路径:自动拼接源文件的完整文件名(含扩展名)
- 相对路径输入:自动解析为相对于当前工作目录的完整路径
- 完整路径输入:直接使用该路径(如果是目录则拼接源文件名)
关于Test-Path的问题
Test-Path -IsValid仅验证路径的语法格式是否符合PowerShell规则,不检查文件名是否符合操作系统的命名规范(比如Windows禁止|、:等字符出现在文件名中)。要验证文件名合法性,必须通过[System.IO.Path]::GetInvalidFileNameChars()获取系统禁止的字符,再检查目标文件名是否包含这些字符——这也是上面函数中合法性验证的核心逻辑。
调用示例及输出
假设当前工作目录为C:\working,源文件为C:\vid\LongVideo.mp4,各调用示例的输出如下:
Resolve-DestinationPath -Path "c:\vid\LongVideo.mp4" -Destination "ShortVideo"C:\working\ShortVideo.mp4Resolve-DestinationPath -Path "c:\vid\LongVideo.mp4" -Destination "ShortVideo.mp4"C:\working\ShortVideo.mp4Resolve-DestinationPath -Path "c:\vid\LongVideo.mp4" -Destination "\ShortVideo.mp4"C:\ShortVideo.mp4Resolve-DestinationPath -Path "c:\vid\LongVideo.mp4" -Destination ".\ShortVideo.mp4"C:\working\ShortVideo.mp4Resolve-DestinationPath -Path "c:\vid\LongVideo.mp4" -Destination "c:\temp"C:\temp\LongVideo.mp4Resolve-DestinationPath -Path "c:\vid\LongVideo.mp4" -Destination "c:\temp\ShortVideo.mp4"C:\temp\ShortVideo.mp4
内容的提问来源于stack exchange,提问作者Ralf_Reddings

