Get-Content似乎使用当前工作目录位置来解析实际路径。但是,.Net System.Io.File Open((方法没有。以PowerShell为中心解析.Net相对路径的方法是什么?
PS C:srct> type .ReadWays.ps1
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[String]$Path
)
Write-Host "Path is $Path"
Get-Content -Path $Path | Out-Null
if ([System.IO.StreamReader]$sr = [System.IO.File]::Open($Path, [System.IO.FileMode]::Open)) { $sr.Close() }
PS C:srct> .ReadWays.ps1 -Path '.t.txt'
Path is .t.txt
MethodInvocationException: C:srctReadWays.ps1:8
Line |
8 | if ([System.IO.StreamReader]$sr = [System.IO.File]::Open($Path, [Syst …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Exception calling "Open" with "2" argument(s): "Could not find file 'C:Program FilesPowerShell7t.txt'."
PS C:srct> $PSVersionTable.PSVersion.ToString()
7.2.0
您可以添加一个测试来查看路径是否是相对的,如果是,则将其转换为绝对路径,如:
if (![System.IO.Path]::IsPathRooted($Path) -or $Path -match '^\[^\]+') {
$path = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($pwd, $Path))
}
我添加了$Path -match '^\[^\]+'
来转换以反斜杠开头的相对路径,如ReadWays.ps1
,这意味着路径从根目录开始。以两个反斜杠开头的UNC路径被视为绝对路径
以下内容对我来说很好,并且与Windows兼容和Linux。这是使用Convert-Path
来解析相对路径。我以前使用的是Resolve-Path
,这是不正确的,只有前者解析为文件系统本机路径,感谢mklement0指出
param(
[ValidateScript({
if(Test-Path $_ -PathType Leaf)
{
return $true
}
throw 'Invalid File Path'
})]
[string]$Path
)
if(-not $Path.StartsWith('\'))
{
[string]$Path = Convert-Path $Path
}
$reader = [System.IO.StreamReader]::new(
[System.IO.File]::Open(
$Path, [System.IO.FileMode]::Open
)
)
$reader.BaseStream
$reader.Close()
上次编辑
以下应该能够处理:
- UNC路径
- 在Windows和Linux上工作
- 高效
- 处理相对路径
从$Path
由于ValidateScript attribute
而有效的基础开始,我们只需要确定我们处理的路径是UNC、Relative还是Absolute。
UNC路径必须始终完全限定。它们可以包括相对的目录段(.和..(,但它们必须是完全限定路径的一部分。只能通过将UNC路径映射到驱动器号来使用相对路径。
我们可以假设UNC路径必须始终以\
开头,因此这个条件应该足以确定$Path
是否会被操纵:
if(-not $Path.StartsWith('\'))
最后,在begin
块中,每次脚本或函数运行时更新环境的当前目录:
[Environment]::CurrentDirectory = $pwd.ProviderPath
通过这样做,([System.IO.FileInfo]$Path).FullName
应该为我们提供参数的绝对路径,无论是UNC、Relative还是absolute。
param(
[ValidateScript({
if(Test-Path $_ -PathType Leaf) {
return $true
}
throw 'Invalid File Path'
})] [string]$Path
)
begin
{
[Environment]::CurrentDirectory = $pwd.ProviderPath
}
process
{
if(-not $Path.StartsWith('\'))
{
$Path = ([System.IO.FileInfo]$Path).FullName
}
try
{
$reader = [System.IO.StreamReader]::new(
[System.IO.File]::Open(
$Path, [System.IO.FileMode]::Open
)
)
$reader.BaseStream
}
catch
{
$_.Exception.Message
}
finally
{
$reader.Close()
$reader.Dispose()
}
}
这是一个常见的问题。不知怎的.net和powershell在当前目录上不一致。
[System.IO.File]::Open("$pwd$Path", [System.IO.FileMode]::Open)