【问题标题】:How can I read file input without any pre-defined path in PowerShell?如何在 PowerShell 中没有任何预定义路径的情况下读取文件输入?
【发布时间】:2017-05-25 10:56:30
【问题描述】:

我让用户提供一个输入 txt 文件作为参数 -InputFile,我将其存储为 $inputfile。但是当我尝试时:

$reader = [System.IO.File]::OpenText("$inputfile")

PowerShell 自动将 $inputfile 路径附加到 C:\Windows\system32。我如何让 PowerShell 不假定路径前缀,因此如果用户想要的文件与运行脚本的目录位于同一目录中,则用户可以简单地传递 -InputFile inputfile.txt?如果文件不在当前目录之外,我怎么能支持他们枚举一个完全不同的文件路径而不让它自动附加到 C:\Windows\system32?

编辑:根据您的建议将变量“$input”更改为“$inputfile”。

【问题讨论】:

    标签: windows file powershell io powershell-2.0


    【解决方案1】:

    在将路径传递给OpenText() 之前/之后使用Resolve-Path 解析路径:

    $reader = [IO.File]::OpenText((Resolve-Path $InputFile).Path)
    

    由于Resolve-Path 在无法解析路径时会引发异常,因此您可能希望在try..catch 块中运行它,例如像这样:

    try {
        $path = (Resolve-Path $InputFile).Path
        $reader = [IO.File]::OpenText($path)
    } catch [Management.Automation.ItemNotFoundException] {
        # cannot resolve path
    } catch {
        # other error
    }
    

    或者,更好的是,验证参数:

    [Parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [ValidateScript({Test-Path -LiteralPath $_ -Type Leaf})]
    [string]$InputFile
    

    【讨论】:

    • 删除了我对 Resolve-Path 的回答。不过,我建议 OP 采取措施验证解决方案,以避免出现意外结果。
    • 是的。相应地更新了我的答案。
    【解决方案2】:

    首先我想支持其他人所说的:你不应该使用$Input 作为你的变量名,因为这是一个自动变量。

    除此之外,我想为您提供一个替代方案。就我个人而言,我保留了一个函数,当我希望人们指定输入文件时,它会弹出一个打开文件对话框。

    Function Get-FilePath{
    [CmdletBinding()]
    Param(
        [String]$Filter = "All Files (*.*)|*.*|Comma Seperated Values (*.csv)|*.csv|Text Files (*.txt)|*.txt",
        [String]$InitialDirectory = "C:\",
        [String]$Title)
    
        [void][System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
        $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
        $OpenFileDialog.initialDirectory = $InitialDirectory
        $OpenFileDialog.filter = $Filter
        $OpenFileDialog.Title = $Title
        [void]$OpenFileDialog.ShowDialog()
        $OpenFileDialog.filename
    }
    

    然后你可以做类似的事情

    $InputFilePath = Get-FilePath
    

    这将为您提供文件的完整路径作为字符串。

    【讨论】:

      【解决方案3】:

      首先:请注意,$input 是 PowerShell 中的一个特殊变量。有关更多信息,请参阅help about_Automatic_Variables。 (您没有在问题中提供足够的上下文,让我知道您是否正确使用了该变量。)

      其次,.NET 对象不假定与 PowerShell 相同的工作位置。他们不能,因为 PowerShell 具有文件系统驱动器以外的“驱动器”。如果你确定你在文件系统中,你可以使用这样的东西:

      $fullPath = Join-Path (Get-Location).Path $inputFilenameFromUser
      

      Cmdlet 将使用工作位置。

      【讨论】:

        【解决方案4】:

        首先,不要使用$input作为变量名;它是automatic variable,因此它可能会被覆盖或产生意外结果。

        第二,你确定“当前”目录不是C:\Windows\System32吗?工作目录不一定是(而且通常不是)脚本所在的路径。

        如果您希望它始终使用脚本目录而不是工作目录,但仅当路径是相对的时,那么您必须进行一些编码以确保(注意我将您的 $input 变量替换为一个叫$Path):

        if (($Path | Split-Path -IsAbsolute)) {
            $reader = [System.IO.File]::OpenText($Path)
        } else {
            $myPath = $PSScriptRoot | Join-Path -ChildPath $Path
            $reader = [System.IO.File]::OpenText($myPath)
        }
        

        【讨论】:

          猜你喜欢
          • 2013-06-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-05-24
          • 2023-02-09
          • 2014-04-29
          • 1970-01-01
          相关资源
          最近更新 更多