Quero testar se existe um alias com o seguinte código:
if( (get-alias ls) ) {
echo "=> Alias ls already exists."
} else {
echo "=> Alias ls does not exist."
}
Quando executado, ele diz:
CommandType Name Version Source
----------- ---- ------- ------
Alias ls -> Get-ChildItem
=> Alias ls already exits.
Tentei redirecionar a saída do comando para $null :
if( (get-alias ls >$null) ) {
echo "=> Alias ls already exits."
} else {
echo "=> Alias ls does not exist."
}
Eu esperava esta saída quando executado:
=> Alias ls already exists.
Mas o resultado do trecho de código mudou de alguma forma:
=> Alias ls does not exist.
Se eu redirecionar após o primeiro conjunto de parênteses, também obtenho:
=> Alias ls does not exist.
Por que o redirecionamento interfere no resultado?
If
testa se há ou não saída, não o código de resultado$?
do comando. Você pode combinar duas instruções com$( )
.Porque ao redirecionar o Success Stream (também conhecido como stdOut) para
$null
nada resta a ser avaliadoif
, o que resulta em uma$false
detecção.Você pode usar em vez disso
Desta forma
If
será avaliado se algum valor não falso foi armazenado na variável associada, neste caso$null
para que seja descartado imediatamenteUsar
Get-Alias
um alias inexistente lançará um erro contínuo e retornará um$null
.-ErrorAction SilentlyContinue
ocultará o erro (enquanto ainda o registra em$Error
) e, como um$null
valor foi armazenado,if
detectará$false
E, claro, se
Get-Alias
retornar um valor,if
ele detectará$true
e, como o valor foi armazenado nele$null
, será imediatamente destruído.Para complementar as respostas úteis existentes:
Na verdade - ao contrário de shells compatíveis com POSIX, como
bash
- os condicionais do PowerShell atuam na saída do fluxo de sucesso de um comando que está sendo testado, não em seu status de sucesso (conforme refletido na variável automática$?
). [1]Se a saída ainda não for um booleano (
$true
ou$false
), ela será convertida em um , usando as regras descritas no tópico de ajuda about_Booleans .Por exemplo, um comando que não produz nenhuma saída é interpretado como
$false
-, o que pode ou não estar correlacionado com o comando também sinalizando uma condição de erro por meio$?
da reflexão de$false
.Entretanto, no PowerShell (Core) 7 , a edição multiplataforma de instalação sob demanda do PowerShell, há formulários condicionais que atuam em
$?
, ou seja, no status de sucesso, assim como em shells compatíveis com POSIX , dos quais o recurso foi emprestado, ou seja, na forma de&&
e||
nos operadores de cadeia de pipeline :command-a && command-b
executacommand-b
somente se forcommand-a
bem-sucedido (se$?
for$true
)command-a || command-b
executacommand-b
somente secommand-a
falhou (emitiu pelo menos um erro, nesse caso$?
é$false
)Como suas contrapartes POSIX-shell, eles não consomem a saída do comando e agem apenas no sucesso ou na falha dos comandos, conforme implícito em
$?
Segue-se que usar expressões em vez de comandos com esses operadores é de uso limitado, pois eles normalmente não causam erros e, portanto, não causam
$?
reflexão$false
; no entanto, há exceções (mas observe que, na ausência deles,try ... catch
a mensagem de erro não pode ser suprimida):1 / 0 || 'failed!'
[int]::Parse('NotANumber') || 'failed!'
Entretanto, uma limitação fundamental é que os operadores só podem encadear pipelines , ou seja, comandos e expressões (únicos) , e não também instruções de linguagem (com base em palavras-chave) , incluindo notavelmente
exit
; para isso, é necessário o uso de$(...)
, o operador de subexpressão :não funciona , porqueGet-Item NoSuch || exit 1
exit
é uma declaração de linguagem.Get-Item NoSuch || $(exit 1)
obras, devido a$(...)
Aplicado ao seu caso:
Usando
&&
e||
:*>$null
para suprimir a saída de todos os fluxos, o que é necessário porque, como observado,&&
e||
por design , não consome silenciosamente nenhum fluxo de saída, ou seja, também não consome silenciosamente o fluxo de saída de sucesso (que é o que os condicionais regulares do PowerShell consomem).Usando uma
if
declaração regular, como alternativa às soluções nas outras respostas: Você pode usar umaTest-Path
chamada para testar a existência de um alias, por meio daAlias:
unidade publicada pelo provedor de alias :Test-Path
emite apenas$true
ou$false
, então não há saída de erro para suprimir.Isso funciona de forma análoga para outros provedores do PowerShell ; por exemplo, você pode usar
Test-Path Function:Foo
para testar a existência de umaFoo
função ouTest-Path Env:Bar
para testar a existência de uma variável de ambiente chamadaBar
.[1] É a contrapartida da variável de mesmo nome em shells compatíveis com POSIX; no entanto, esta última contém o código de saída do comando executado mais recentemente, enquanto no PowerShell é um Booleano :
$true
indica execução bem-sucedida (sem erros), enquanto$false
implica que (pelo menos um) erro ocorreu. No contexto de chamadas para programas externos , um código de saída de0
é refletido como$true
em$?
, e qualquer código de saída diferente de zero como$false
.Os comandos nativos do PowerShell não usam códigos de saída, mas o PowerShell fornece a variável automática
$LASTEXITCODE
para refletir o código de saída do programa externo executado mais recentemente (e também de scripts do PowerShell (*.ps1
arquivos) se eles usaremexit
com um número para sair).