代码之家  ›  专栏  ›  技术社区  ›  Eamon Nerbonne

PowerShell:解析可能不存在的路径?

  •  43
  • Eamon Nerbonne  · 技术社区  · 14 年前

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

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

    注意 System.IO.Path 的静态方法与 过程的 工作目录-不是PowerShell当前位置。

    11 回复  |  直到 6 年前
        1
  •  68
  •   x0n    14 年前

    你想要:

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

    返回:

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

    这有使用pspath的优势,而不是本地文件系统路径。pspath可能无法将1-1映射到文件系统路径,例如,如果使用多字母驱动器名安装psdrive。

    -奥辛

        2
  •  22
  •   information_interchange    7 年前

    什么时候? 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
    }
    
        3
  •  13
  •   Keith Hill    14 年前

    我觉得你走对了。只需使用[environment]::currentdirectory设置.net对进程当前目录的概念,例如:

    [Environment]::CurrentDirectory = $pwd
    [IO.Path]::GetFullPath(".\xyz")
    
        4
  •  5
  •   Community CDub    7 年前

    这样做的好处是不必设置clr环境的当前目录:

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

    注释

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

        5
  •  1
  •   savagent    10 年前

    我发现下面的方法很有效。

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

    convert path可用于获取字符串形式的路径,尽管情况并非总是如此。见 this 有关详细信息,请输入convert path。

        6
  •  1
  •   Joel Francis    7 年前

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

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

    这只是验证路径中是否没有非法字符,以及该路径是否可用于存储文件。如果目标不存在, Test-Path 在这个实例中不关心——它只是被要求测试提供的路径是否潜在有效。

        7
  •  1
  •   Max Toro    7 年前
    Join-Path (Resolve-Path .) newdir\newfile.txt
    
        8
  •  0
  •   user133580    11 年前
    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;
            }
        }
    }
    
        9
  •  0
  •   Igor    6 年前

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

    $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 阻止,但这是不可能的。

        10
  •  -1
  •   Andy Schneider    14 年前

    您只需将-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
  •   shane carvalho    14 年前

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

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