How can I read file input without any pre-defined path in PowerShell?

做~自己de王妃 提交于 2019-12-25 09:19:09

问题


I have users provide an input txt file as an argument -InputFile which I store as $inputfile. But when I try:

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

PowerShell automatically appends the $inputfile path to C:\Windows\system32. How can I have PowerShell not assume a path prefix, so a user could simply pass -InputFile inputfile.txt if the file they want is in the same directory from which they run the script? How can I also support them enumerating a completely different path to the file if it's outside of the current directory without having it automatically append to C:\Windows\system32?

EDIT: Changed the variable "$input" to "$inputfile" per your advice.


回答1:


Use Resolve-Path for resolving the path before/when you pass it to OpenText():

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

Since Resolve-Path throws an exception when it can't resolve a path you may want to run this in a try..catch block, e.g. like this:

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

or, better yet, validate the parameter:

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



回答2:


First: Be aware that $input is a special variable in PowerShell. See help about_Automatic_Variables for more information. (You don't put enough context in your question for me to know whether you're using that variable properly or not.)

Second, .NET objects don't assume the same working location as PowerShell. They can't, because PowerShell has "drives" other than file system drives. If you're sure you're in the file system, you can use something like this:

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

Cmdlets will use the working location.




回答3:


First, don't use $input as a variable name; it's an automatic variable so it could be overwritten or have unexpected results.

Second, are you sure that the "current" directory is not C:\Windows\System32? The working directory is not necessarily (and often isn't) the path where the script is.

If you want it to always use the script directory instead of the working directory, but only when the path is relative, then you have to do some coding to make sure (note I'm replacing your $input variable with one called $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)
}



回答4:


First I'd like to second what everybody else has said: that you should not be using $Input as your variable name since that is an automatic variable.

Aside from that I'd like to offer you an alternative. Personally I keep a function around that will pop up an Open File dialog box when I want people to specify an input file.

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
}

Then you could just do something like

$InputFilePath = Get-FilePath

That would give you the full path to the file as a string.



来源:https://stackoverflow.com/questions/41577526/how-can-i-read-file-input-without-any-pre-defined-path-in-powershell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!