powershell获取内容和.Net Open()的处理路径不同



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)

最新更新