如何在 PowerShell 中没有任何预定义路径的情况下读取文件输入?
How can I read file input without any pre-defined path in PowerShell?
我让用户提供一个输入 txt 文件作为参数 -InputFile
,我将其存储为 $inputfile
。但是当我尝试时:
$reader = [System.IO.File]::OpenText("$inputfile")
PowerShell 自动将 $inputfile
路径附加到 C:\Windows\system32。我怎样才能让 PowerShell 不假定路径前缀,以便用户可以简单地传递 -InputFile inputfile.txt
如果他们想要的文件位于他们 运行 脚本所在的同一目录中?如果文件在当前目录之外,我如何才能支持他们枚举一个完全不同的文件路径,而不让它自动附加到 C:\Windows\system32?
编辑:根据您的建议将变量“$input”更改为“$inputfile”。
首先,不要使用$input
作为变量名;这是一个 automatic variable,因此它可能会被覆盖或产生意外结果。
其次,你确定"current"目录不是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)
}
使用 Resolve-Path
解析你传递给 OpenText()
的路径 before/when:
$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
首先:请注意$input
是PowerShell 中的一个特殊变量。有关详细信息,请参阅 help about_Automatic_Variables
。 (你没有在你的问题中提供足够的上下文让我知道你是否正确使用了那个变量。)
其次,.NET 对象不采用与 PowerShell 相同的工作位置。他们不能,因为 PowerShell 除了文件系统驱动器之外还有 "drives"。如果你确定你在文件系统中,你可以使用这样的东西:
$fullPath = Join-Path (Get-Location).Path $inputFilenameFromUser
Cmdlet 将使用工作位置。
首先,我想赞同其他人所说的:你不应该使用 $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
这将为您提供文件的完整路径作为字符串。
我让用户提供一个输入 txt 文件作为参数 -InputFile
,我将其存储为 $inputfile
。但是当我尝试时:
$reader = [System.IO.File]::OpenText("$inputfile")
PowerShell 自动将 $inputfile
路径附加到 C:\Windows\system32。我怎样才能让 PowerShell 不假定路径前缀,以便用户可以简单地传递 -InputFile inputfile.txt
如果他们想要的文件位于他们 运行 脚本所在的同一目录中?如果文件在当前目录之外,我如何才能支持他们枚举一个完全不同的文件路径,而不让它自动附加到 C:\Windows\system32?
编辑:根据您的建议将变量“$input”更改为“$inputfile”。
首先,不要使用$input
作为变量名;这是一个 automatic variable,因此它可能会被覆盖或产生意外结果。
其次,你确定"current"目录不是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)
}
使用 Resolve-Path
解析你传递给 OpenText()
的路径 before/when:
$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
首先:请注意$input
是PowerShell 中的一个特殊变量。有关详细信息,请参阅 help about_Automatic_Variables
。 (你没有在你的问题中提供足够的上下文让我知道你是否正确使用了那个变量。)
其次,.NET 对象不采用与 PowerShell 相同的工作位置。他们不能,因为 PowerShell 除了文件系统驱动器之外还有 "drives"。如果你确定你在文件系统中,你可以使用这样的东西:
$fullPath = Join-Path (Get-Location).Path $inputFilenameFromUser
Cmdlet 将使用工作位置。
首先,我想赞同其他人所说的:你不应该使用 $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
这将为您提供文件的完整路径作为字符串。