【问题标题】:Accept a path as literal path, relative path or relative to the script root接受路径作为文字路径、相对路径或相对于脚本根目录
【发布时间】:2019-10-31 13:47:36
【问题描述】:

目前我们想在检索文件信息时涵盖这三种情况:

  • 文字路径
  • 相对路径,相对于脚本根目录
  • 相对路径,相对于当前工作目录

为了涵盖这 3 种情况,我们创建了以下函数:

Function Get-FilePathItemHC {
    Param (
        [Parameter(Mandatory)]
        [String]$Path
    )

    $Params = @(
        @{
            # Path relative to the script root
            LiteralPath = Join-Path -Path $PSScriptRoot -ChildPath $Path
        }
        @{
            # Literal or path relative to the present work directory
            Path = $Path
        }
    )

    $Item = $null

    foreach ($P in $Params) {
        if ($Item = Get-Item @P -ErrorAction Ignore) {
            $Item
            Break
        }
    }

    if (-not $Item) {
        throw "Cannot find path '$Path' because it does not exist."
    }
}

这是正确的做法吗?看来我们正在重新发明轮子。

【问题讨论】:

    标签: powershell path


    【解决方案1】:

    将您的-Path 参数设为System.IO.FileInfo 对象,并将相对路径作为参数传入。文件对象将使用相对路径或完整路径解析,然后您可以使用 $path.FullName 引用文件的完整路径。

    Function Get-FilePathItemHC {
        Param (
            [Parameter(Mandatory)]
            [ValidateScript({ $_.Exists })]
            [System.IO.FileInfo]$Path
        )
    
        # The ValidateScript attribute makes sure the file you passed in exists
        # so your validation code no longer is required
    }
    

    如果您想同时处理目录和文件,则在这种情况下您可能需要两个单独的变量,因为目录路径将成为 System.IO.DirectoryInfo 对象,但您可以使参数互斥:

    Function Get-FilePathItemHC {
    Param (
        [Parameter(Mandatory=$true, ParameterSetName="FilePath")]
        [ValidateScript({ $_.Exists })]
        [System.IO.FileInfo]$FilePath,
        [Parameter(Mandatory=$true, ParameterSetName="DirectoryPath")]
        [ValidateScript({ $_.Exists })]
        [System.IO.DirectoryInfo]$DirectoryPath
    )
    
      $Path = $FilePath
      if( $DirectoryPath ) {
        $Path = $DirectoryPath
      }
    
      # The ValidateScript attribute makes sure the file you passed in exists
      # so your validation code no longer is required
    }
    
    Get-FilePathItemHC -Path .\path\to\file.txt
    

    $PSScriptRoot获取相对路径

    如果您已经拥有文件的完整路径,我不确定为什么需要相对于 $PSScriptRoot 的路径,但是在获取 System.IO.FileInfoSystem.IO.DirectoryInfo 对象后,您可以使用来自 @ 的 Resolve-Path 987654332@ 获取该目录的相对路径:

    $file = Get-FilePathItemHC -Path .\path\to\file.txt
    Push-Location $PSScriptRoot
    $relativeFromScriptRootPath = Resolve-Path -Relative $file
    Pop-Location
    

    Push-LocationPop-Location 将位置视为堆栈。 push 操作设置一个新位置并将其添加到堆栈中,pop 操作从堆栈中删除最后添加的位置并将您放置在下一个最近的位置。如果你熟悉的话,它有点像 Linux 上的cd -

    Resolve-Path 将返回一个文件路径,-Relative 开关将返回一个相对于您当前目录的路径。您不能传入备用目录来解析,这就是我们更改运行位置的原因。

    【讨论】:

    • 谢谢@Bender,但我要找出的是相对于脚本根文件夹的路径、常规相对路径或文字路径。恐怕你的代码不会涵盖第一种情况。
    • 查看我使用Resolve-Path$PSScriptRoot获取相对路径的更新答案
    • 从未听说过Push-LocationPop-Location。很好的提示,谢谢! :)
    • 在我的$profile 中,我实际上将cd 别名为Push-Location,并将pd 别名为Pop-Location。我对缺少cd - 的解决方案无需使用pushdpopd 的完整cmdlet 名称或更长的别名
    猜你喜欢
    • 2016-01-09
    • 2013-04-17
    • 2014-04-14
    • 1970-01-01
    • 2015-02-09
    • 2019-07-08
    • 2011-05-27
    • 2012-08-29
    • 2012-01-11
    相关资源
    最近更新 更多