2017-01-10 11 views
0

У меня есть пользовательский входной файл txt в качестве аргумента -InputFile, который я хранил как $inputfile. Но когда я пытаюсь:Как я могу прочитать ввод файла без какого-либо заранее определенного пути в PowerShell?

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

PowerShell автоматически добавляет $inputfile путь к C: \ Windows \ system32. Как я могу заставить PowerShell не использовать префикс пути, поэтому пользователь может просто передать -InputFile inputfile.txt, если файл, который они хотят, находится в том же каталоге, из которого они запускают скрипт? Как я могу также поддерживать их перечисление совершенно другого пути к файлу, если он находится за пределами текущего каталога, без автоматического добавления в C: \ Windows \ system32?

EDIT: Изменил переменную «$ input» на «$ inputfile» за ваш совет.

ответ

1

Использование Resolve-Path для разрешения пути до /, когда вы передаете его OpenText():

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

Поскольку Resolve-Path бросает исключение, когда я t не может разрешить путь, который вы, возможно, захотите запустить, в блоке 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 
+1

Убрал мой ответ в знак уважения к Решению пути. Однако я рекомендую, чтобы OP предпринял шаги для проверки разрешения, чтобы избежать получения неожиданного результата. –

+0

Правда. Обновил мой ответ соответственно. –

0

Во-первых, не используйте $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) 
} 
2

Во-первых: Имейте в виду, что $input специальная переменная в PowerShell. См. help about_Automatic_Variables для получения дополнительной информации. (Вы не задаете достаточно контекста в своем вопросе, чтобы узнать, используете ли вы эту переменную правильно или нет.)

Во-вторых, объекты .NET не предполагают то же рабочее место, что и PowerShell. Они не могут, потому что у PowerShell есть «диски», кроме дисков файловой системы. Если вы уверены, что вы находитесь в файловой системе, вы можете использовать что-то вроде этого:

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

командлеты будет использовать рабочее местоположение.

0

Прежде всего, я хотел бы повторить то, что сказали все остальные: что вы не должны использовать $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 

Это даст вам полный путь к файлу в виде строки.