Powershell: определить путь, который может не существовать? - PullRequest
48 голосов
/ 14 июня 2010

Я пытаюсь обработать список файлов, которые могут обновляться или не обновляться, а могут и не существовать.При этом мне нужно разрешить полный путь элемента, даже если элемент может быть указан с относительными путями.Однако Resolve-Path печатает и выдает ошибку при использовании с несуществующим файлом.

Например, Какой самый простой и чистый способ разрешения ".\newdir\newfile.txt" до "C:\Current\Working\Directory\newdir\newfile.txt" в Powershell ?

Обратите внимание, что статический метод System.IO.Path используется с рабочим каталогом процесса , который не является текущим местоположением powershell.

Ответы [ 11 ]

73 голосов
/ 15 июня 2010

Вы хотите:

c:\path\exists\> $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(".\nonexist\foo.txt")

возвращает:

c:\path\exists\nonexists\foo.txt

Это имеет преимущество работы с PSPaths, а не с собственными путями файловой системы.PSPAth может не отображать 1-1 на путь файловой системы, например, если вы монтируете psdrive с именем диска из нескольких букв.

-Oisin

23 голосов
/ 26 сентября 2012

При сбое Resolve-Path из-за несуществующего файла доступ к полностью разрешенному пути возможен из брошенного объекта ошибки.

Вы можете использовать функцию, подобную следующей, чтобы исправить Resolve-Path и заставить его работатькак вы ожидаете.

function Force-Resolve-Path {
    <#
    .SYNOPSIS
        Calls Resolve-Path but works for files that don't exist.
    .REMARKS
        From http://devhawk.net/blog/2010/1/22/fixing-powershells-busted-resolve-path-cmdlet
    #>
    param (
        [string] $FileName
    )

    $FileName = Resolve-Path $FileName -ErrorAction SilentlyContinue `
                                       -ErrorVariable _frperror
    if (-not($FileName)) {
        $FileName = $_frperror[0].TargetObject
    }

    return $FileName
}
13 голосов
/ 14 июня 2010

Я думаю, вы на правильном пути. Просто используйте [Environment] :: CurrentDirectory, чтобы установить .NET представление о текущем каталоге процесса, например ::100100

[Environment]::CurrentDirectory = $pwd
[IO.Path]::GetFullPath(".\xyz")
5 голосов
/ 16 мая 2014

Преимуществом этого является отсутствие необходимости устанавливать текущий каталог среды CLR:

[IO.Path]::Combine($pwd,"non\existing\path")

ПРИМЕЧАНИЕ

Это функционально не эквивалентно x0n-ответу .System.IO.Path.Combine только объединяет сегменты пути строки.Его основная утилита не дает разработчику беспокоиться о косых чертах.GetUnresolvedProviderPathFromPSPath будет проходить путь ввода относительно текущего рабочего каталога в соответствии с . и ...

4 голосов
/ 23 ноября 2017
Join-Path (Resolve-Path .) newdir\newfile.txt
1 голос
/ 13 ноября 2017

Здесь есть принятый ответ, но он довольно длинный и есть более простая альтернатива.

В любой последней версии Powershell вы можете использовать Test-Path -IsValid -Path 'C:\Probably Fake\Path.txt'

Это просто подтверждает, что в пути нет недопустимых символов и что путь можно использовать для хранения файла. Если цель не существует, Test-Path в этом случае не заботится - ее только просят проверить, является ли указанный путь потенциально допустимым.

1 голос
/ 02 декабря 2014

Я обнаружил, что следующее работает достаточно хорошо.

$workingDirectory = Convert-Path (Resolve-Path -path ".")
$newFile = "newDir\newFile.txt"
Do-Something-With "$workingDirectory\$newFile"

Convert-Path может использоваться для получения пути в виде строки, хотя это не всегда так. См. эту запись в COnvert-Path для более подробной информации.

0 голосов
/ 23 октября 2018

Я получил этот код в моем случае.Позже мне нужно было создать файл в скрипте, поэтому этот код предполагает, что у вас есть права на запись в целевую папку.

$File = ".\newdir\newfile.txt"
If (Test-Path $File) {
    $Resolved = (Resolve-Path $File).Path
} else {
    New-Item $File -ItemType File | Out-Null
    $Resolved = (Resolve-Path $File).Path
    Remove-Item $File
}

Я также заключил New-Item в блок try..catch, но это выходитэтого вопроса.

0 голосов
/ 05 августа 2013
function Get-FullName()
{
    [CmdletBinding()]
    Param(
        [Parameter(ValueFromPipeline = $True)] [object[]] $Path
    )
    Begin{
        $Path = @($Path);
    }
    Process{
        foreach($p in $Path)
        {
            if($p -eq $null -or $p -match '^\s*$'){$p = [IO.Path]::GetFullPath(".");}
            elseif($p -is [System.IO.FileInfo]){$p = $p.FullName;}
            else{$p = [IO.Path]::GetFullPath($p);}
            $p;
        }
    }
}
0 голосов
/ 15 июня 2010

Проверьте, существует ли файл перед разрешением:

if(Test-Path .\newdir\newfile.txt) { (Resolve-Path .\newdir\newfile.txt).Path }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...