Лучший способ проверить, существует ли путь или нет в PowerShell


мне просто не нравится синтаксис:

if (Test-Path $path) { ... }

и

if (-not (Test-Path $path)) { ... }
if (!(Test-Path $path)) { ... }

особенно есть слишком много скобок и не очень читается при проверке на "не существует" для такого общего использования. Что является лучшим способом сделать это?

обновление: мое текущее решение-использовать псевдонимы для exist и not-exist как пояснил здесь.

связанная проблема в репозитории PowerShell: https://github.com/PowerShell/PowerShell/issues/1970

3 56

3 ответа:

если вам просто нужна альтернатива синтаксису командлета, в частности для файлов, используйте File.Exists() .Чистый способ:

if(![System.IO.File]::Exists($path)){
    # file with path $path doesn't exist
}

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

# Gather command meta data from the original Cmdlet (in this case, Test-Path)
$TestPathCmd = Get-Command Test-Path
$TestPathCmdMetaData = New-Object System.Management.Automation.CommandMetadata $TestPathCmd

# Use the static ProxyCommand.GetParamBlock method to copy 
# Test-Path's param block and CmdletBinding attribute
$Binding = [System.Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($TestPathCmdMetaData)
$Params  = [System.Management.Automation.ProxyCommand]::GetParamBlock($TestPathCmdMetaData)

# Create wrapper for the command that proxies the parameters to Test-Path 
# using @PSBoundParameters, and negates any output with -not
$WrappedCommand = { 
    try { -not (Test-Path @PSBoundParameters) } catch { throw $_ }
}

# define your new function using the details above
$Function:notexists = '{0}param({1}) {2}' -f $Binding,$Params,$WrappedCommand

notexists теперь будет вести себя ровно как Test-Path, но всегда возвращайте противоположный результат:

PS C:\> Test-Path -Path "C:\Windows"
True
PS C:\> notexists -Path "C:\Windows"
False
PS C:\> notexists "C:\Windows" # positional parameter binding exactly like Test-Path
False

как вы уже показали, наоборот довольно легко, просто псевдоним exists до Test-Path:

PS C:\> New-Alias exists Test-Path
PS C:\> exists -Path "C:\Windows"
True

решение псевдонимов, которое вы опубликовали, умно, но я бы возражал против его использования в скриптах, по той же причине, по которой мне не нравится использовать какие-либо псевдонимы в скриптах; это имеет тенденцию вредить читаемости.

Если это то, что вы хотите добавить в свой профиль, чтобы вы могли вводить быстрые команды или использовать его в качестве оболочки, тогда я мог бы увидеть, что это имеет смысл.

вместо этого вы можете рассмотреть трубопроводы:

if ($path | Test-Path) { ... }
if (-not ($path | Test-Path)) { ... }
if (!($path | Test-Path)) { ... }

альтернативно, для отрицательного подхода, если это уместно для ваш код, вы можете сделать его положительной проверкой, а затем использовать else для отрицательных:

if (Test-Path $path) {
    throw "File already exists."
} else {
   # The thing you really wanted to do.
}

добавьте следующие псевдонимы. Я думаю, они должны быть доступны в PowerShell по умолчанию:

function not-exist { -not (Test-Path $args) }
Set-Alias !exist not-exist -Option "Constant, AllScope"
Set-Alias exist Test-Path -Option "Constant, AllScope"

при этом условные операторы изменятся на:

if (exist $path) { ... }

и

if (not-exist $path)) { ... }
if (!exist $path)) { ... }