当前,我们在检索文件信息时涉及这三种情况:
为涵盖这3种情况,我们创建了以下函数:
Function Get-FilePathItemHC {
Param (
[Parameter(Mandatory)]
[String]$Path
)
$Params = @(
@{
# Path relative to the script root
LiteralPath = Join-Path -Path $PSScriptRoot -ChildPath $Path
}
@{
# Literal or path relative to the present work directory
Path = $Path
}
)
$Item = $null
foreach ($P in $Params) {
if ($Item = Get-Item @P -ErrorAction Ignore) {
$Item
Break
}
}
if (-not $Item) {
throw "Cannot find path '$Path' because it does not exist."
}
}
这是正确的做法吗?看来我们在这里重新发明轮子。
答案 0 :(得分:1)
为您的-Path
参数设置一个System.IO.FileInfo
对象,然后传入一个相对路径作为参数。文件对象将使用相对路径或完整路径进行解析,然后您可以使用$path.FullName
来引用文件的完整路径。
Function Get-FilePathItemHC {
Param (
[Parameter(Mandatory)]
[ValidateScript({ $_.Exists })]
[System.IO.FileInfo]$Path
)
# The ValidateScript attribute makes sure the file you passed in exists
# so your validation code no longer is required
}
如果要同时处理目录和文件,则在这种情况下,您将需要具有两个单独的变量,因为目录路径将成为System.IO.DirectoryInfo
对象,但是可以使参数互斥:
Function Get-FilePathItemHC {
Param (
[Parameter(Mandatory=$true, ParameterSetName="FilePath")]
[ValidateScript({ $_.Exists })]
[System.IO.FileInfo]$FilePath,
[Parameter(Mandatory=$true, ParameterSetName="DirectoryPath")]
[ValidateScript({ $_.Exists })]
[System.IO.DirectoryInfo]$DirectoryPath
)
$Path = $FilePath
if( $DirectoryPath ) {
$Path = $DirectoryPath
}
# The ValidateScript attribute makes sure the file you passed in exists
# so your validation code no longer is required
}
Get-FilePathItemHC -Path .\path\to\file.txt
$PSScriptRoot
如果您已经拥有文件的完整路径,我不确定为什么需要相对于$PSScriptRoot
的路径,但是在获取System.IO.FileInfo
或System.IO.DirectoryInfo
对象之后,您可以使用Resolve-Path
中的$PSScriptRoot
从该目录获取相对路径:
$file = Get-FilePathItemHC -Path .\path\to\file.txt
Push-Location $PSScriptRoot
$relativeFromScriptRootPath = Resolve-Path -Relative $file
Pop-Location
Push-Location
和Pop-Location
将位置视为堆栈。 push
操作会设置一个新位置并将其添加到堆栈中,而pop
操作会从堆栈中删除最后添加的位置,并将您放置在下一个最近的位置。如果您熟悉的话,在Linux上的工作原理类似于cd -
。
Resolve-Path
将返回文件路径,而-Relative
开关将返回相对于当前目录的路径。您无法传递替代目录来解析,这就是为什么我们更改了运行该目录的原因。