Powershell:解决可能不存在的路径?

时间:2010-06-14 15:09:55

标签: powershell

我正在尝试处理可能是也可能不是最新的文件列表,可能存在也可能不存在。在这样做时,我需要解析项目的完整路径,即使该项目可能使用相对路径指定。但是,Resolve-Path在与不存在的文件一起使用时会打印并出错。

例如,在Powershell中解析".\newdir\newfile.txt""C:\Current\Working\Directory\newdir\newfile.txt"的最简单,最干净的方法是什么?

请注意,System.IO.Path的静态方法与进程的工作目录一起使用 - 这不是powershell的当前位置。

13 个答案:

答案 0 :(得分:71)

你想:

c:\path\exists\> $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(".\nonexist\foo.txt")

返回:

c:\path\exists\nonexists\foo.txt

这样做的好处是可以使用PSPath,而不是本机文件系统路径。 PSPAth可能不会将1-1映射到文件系统路径,例如,如果您使用多字母驱动器名称挂载psdrive。

-Oisin

答案 1 :(得分:23)

Resolve-Path由于文件不存在而失败时,可以从抛出的错误对象访问完全解析的路径。

您可以使用以下功能修复Resolve-Path并使其按预期工作。

function Force-Resolve-Path {
    <#
    .SYNOPSIS
        Calls Resolve-Path but works for files that don't exist.
    .REMARKS
        From http://devhawk.net/blog/2010/1/22/fixing-powershells-busted-resolve-path-cmdlet
    #>
    param (
        [string] $FileName
    )

    $FileName = Resolve-Path $FileName -ErrorAction SilentlyContinue `
                                       -ErrorVariable _frperror
    if (-not($FileName)) {
        $FileName = $_frperror[0].TargetObject
    }

    return $FileName
}

答案 2 :(得分:13)

我认为你走的是正确的道路。只需使用[Environment] :: CurrentDirectory设置.NET的进程当前目录的概念,例如:

[Environment]::CurrentDirectory = $pwd
[IO.Path]::GetFullPath(".\xyz")

答案 3 :(得分:5)

这样做的好处是无需设置CLR环境的当前目录:

[IO.Path]::Combine($pwd,"non\existing\path")

注意

这在功能上与x0n's answer不同。 System.IO.Path.Combine仅组合字符串路径段。它的主要功能是让开发人员不必担心斜线。根据{{​​1}}和GetUnresolvedProviderPathFromPSPath.将遍历相对于当前工作目录的输入路径。

答案 4 :(得分:4)

Join-Path (Resolve-Path .) newdir\newfile.txt

答案 5 :(得分:1)

我发现以下内容效果不错。

$workingDirectory = Convert-Path (Resolve-Path -path ".")
$newFile = "newDir\newFile.txt"
Do-Something-With "$workingDirectory\$newFile"

Convert-Path可用于将路径作为字符串获取,但情况并非总是如此。有关详细信息,请参阅COnvert-Path上的this条目。

答案 6 :(得分:1)

这里有一个公认的答案,但它很长,并且有一个更简单的替代方案。

在任何最新版本的Powershell中,您都可以使用Test-Path -IsValid -Path 'C:\Probably Fake\Path.txt'

这只是验证路径中没有非法字符,并且该路径可用于存储文件。如果目标不存在,Test-Path在这种情况下不会关心 - 它只被要求测试提供的路径是否可能有效。

答案 7 :(得分:0)

function Get-FullName()
{
    [CmdletBinding()]
    Param(
        [Parameter(ValueFromPipeline = $True)] [object[]] $Path
    )
    Begin{
        $Path = @($Path);
    }
    Process{
        foreach($p in $Path)
        {
            if($p -eq $null -or $p -match '^\s*$'){$p = [IO.Path]::GetFullPath(".");}
            elseif($p -is [System.IO.FileInfo]){$p = $p.FullName;}
            else{$p = [IO.Path]::GetFullPath($p);}
            $p;
        }
    }
}

答案 8 :(得分:0)

我最终遇到了这段代码。我需要稍后在脚本中创建一个文件,因此此代码假定您具有对目标文件夹的写访问权。

$File = ".\newdir\newfile.txt"
If (Test-Path $File) {
    $Resolved = (Resolve-Path $File).Path
} else {
    New-Item $File -ItemType File | Out-Null
    $Resolved = (Resolve-Path $File).Path
    Remove-Item $File
}

我也将New-Item放在了try..catch块中,但这没有这个问题。

答案 9 :(得分:0)

我有一个类似的问题,我需要从一个尚不存在的文件夹中向上找到3个文件夹,以确定要创建的新文件夹的名称。这很复杂。无论如何,这就是我最终要做的:

($path -split "\\" | select -SkipLast 3) -join "\\"

答案 10 :(得分:-1)

您可以将-errorAction设置为“SilentlyContinue”并使用Resolve-Path

5 >  (Resolve-Path .\AllFilerData.xml -ea 0).Path
C:\Users\Andy.Schneider\Documents\WindowsPowerShell\Scripts\AllFilerData.xml

6 >  (Resolve-Path .\DoesNotExist -ea 0).Path

7 >

答案 11 :(得分:-1)

两个最流行的答案在不存在的驱动器上的路径上均无法正常工作。

function NormalizePath($filename)
{
    $filename += '\'
    $filename = $filename -replace '\\(\.?\\)+','\'
    while ($filename -match '\\([^\\.]|\.[^\\.]|\.\.[^\\])[^\\]*\\\.\.\\') {
        $filename = $filename -replace '\\([^\\.]|\.[^\\.]|\.\.[^\\])[^\\]*\\\.\.\\','\'
    }
    return $filename.TrimEnd('\')
}

答案 12 :(得分:-2)

在解决之前检查文件是否存在:

if(Test-Path .\newdir\newfile.txt) { (Resolve-Path .\newdir\newfile.txt).Path }