Лучший способ проверить, существует ли путь в 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
Ответы
Ответ 1
Если вам просто нужна альтернатива синтаксису cmdlet, специально для файлов, используйте метод File.Exists()
.NET:
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 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
Ответ 2
Решение псевдонима, которое вы опубликовали, является умным, но я бы возражал против его использования в сценариях, по той же причине, что мне не нравится использование каких-либо псевдонимов в скриптах; он имеет тенденцию ухудшать читаемость.
Если это то, что вы хотите добавить в свой профиль, чтобы вы могли набирать быстрые команды или использовать его в качестве оболочки, тогда я мог видеть, что это имеет смысл.
Вместо этого вы можете использовать трубопровод:
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.
}
Ответ 3
Добавьте следующие псевдонимы. Я думаю, что они должны быть доступны в 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)) { ... }