System.IO.FileInfo 和相对路径

San*_*zon 7 powershell system.io.fileinfo

我想知道是否有人可以帮助我理解为什么System.IO.FileInfo在处理相对路径时 Windows 上的行为与 Linux 上的行为不同。

例子

  • 在 Linux 上
PS /home/user/Documents> ([System.IO.FileInfo]'./test.txt').FullName
/home/user/Documents/test.txt
Run Code Online (Sandbox Code Playgroud)
  • 在 Windows 上
PS C:\Users\User\Documents> ([System.IO.FileInfo]'.\test.txt').FullName
C:\Users\User\test.txt
Run Code Online (Sandbox Code Playgroud)

编辑

System.IO.FileInfo为了澄清上述内容, Windows 或 Linux 上处理相对路径的方式没有区别。该问题与或 未[System.IO.Directory]::GetCurrentDirectory()更新有关。Push-LocationSet-Location

一个简单的例子:

PS /home/user> [System.IO.Directory]::GetCurrentDirectory()
/home/user
PS /home/user> cd ./Documents/
PS /home/user/Documents> [System.IO.Directory]::GetCurrentDirectory()
/home/user
Run Code Online (Sandbox Code Playgroud)

假设这是预期的行为,那么处理param(...)脚本和函数上的块以接受两种情况(绝对和相对)的最佳方法是什么。我曾经输入约束路径参数,System.IO.FileInfo但现在我可以看到它显然是错误的。

这是我遇到的情况,但我想知道是否有更好的方法。
我相信Split-Path -IsAbsolute使用网络路径也会带来问题,如果我错了,请纠正我。

param(
    [ValidateScript({ 
        if(Test-Path $_ -PathType Leaf) {
            return $true
        }
        throw 'Invalid File Path'
    })]
    [string] $Path
)

if(-not (Split-Path $Path -IsAbsolute)) {
    [string] $Path = Resolve-Path $Path
}
Run Code Online (Sandbox Code Playgroud)

The*_*heo 2

感觉有点重复,但既然你问了..

抱歉我不了解 Linux,但是在 Windows 中:

您可以先添加一个测试来查看路径是否是相对路径,如果是,则将其转换为绝对路径,如下所示:

$Path = '.\test.txt'
if (![System.IO.Path]::IsPathRooted($Path) -or $Path -match '^\\[^\\]+') {
    $Path =  [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($pwd, $Path))
}
Run Code Online (Sandbox Code Playgroud)

我添加$Path -match '^\\[^\\]+'还转换以反斜杠开头的相对路径,这\ReadWays.ps1意味着路径从根目录开始。以两个反斜杠开头的 UNC 路径被视为绝对路径。


显然(我真的不知道为什么......)上面的内容在 Linux 上不起作用,因为在那里,当使用 UNC 路径时,该部分![System.IO.Path]::IsPathRooted('\\server\folder')会产生True.

看来你需要先检查操作系统,并在 Linux 上进行不同的检查。

$Path = '\\server\share'

if ($IsWindows) {  # $IsWindows exists in version 7.x. Older versions do `$env:OS -match 'Windows'`
    if (![System.IO.Path]::IsPathRooted($Path) -or $Path -match '^\\[^\\]+') {
        $Path =  [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($pwd, $Path))
    }
}
else {
    if ($Path -notlike '\\*\*') {  # exclude UNC paths as they are not relative
        if (![System.IO.Path]::IsPathRooted($Path) -or $Path -match '^\\[^\\]+') {
            $Path =  [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($pwd, $Path))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)