¿Cuáles son los equivalentes de PowerShell de Bash’s && y || operadores?

En Bash, puedo hacer algo como:

command1 && command2 || command3 

lo que significa ejecutar command1 y si command1 tiene éxito para ejecutar command2 y si command1 falla al ejecutar command3.

¿Cuál es el equivalente en PowerShell?

Lo que Bash debe estar haciendo es emitir implícitamente el código de salida de los comandos a un booleano cuando se pasa a los operadores lógicos. PowerShell no hace esto, pero se puede hacer una función para envolver el comando y crear el mismo comportamiento:

 > function Get-ExitBoolean($cmd) { & $cmd | Out-Null; $? } 

( $? es un bool que contiene el éxito del último código de salida )

Dado dos archivos por lotes:

 #pass.cmd exit 

y

 #fail.cmd exit /b 200 

… el comportamiento puede ser probado:

 > if (Get-ExitBoolean .\pass.cmd) { write pass } else { write fail } pass > if (Get-ExitBoolean .\fail.cmd) { write pass } else { write fail } fail 

Los operadores lógicos se deben evaluar de la misma manera que en Bash. Primero, establece un alias:

 > Set-Alias geb Get-ExitBoolean 

Prueba:

 > (geb .\pass.cmd) -and (geb .\fail.cmd) False > (geb .\fail.cmd) -and (geb .\pass.cmd) False > (geb .\pass.cmd) -and (geb .\pass.cmd) True > (geb .\pass.cmd) -or (geb .\fail.cmd) True 

Muchos años después de que se formuló la pregunta por primera vez, permítanme resumir el estado de las cosas a partir de PowerShell v5.1 :

  • Bash’s / cmd ‘s && y || los operadores de control NO tienen equivalentes de PowerShell , y como no se pueden definir operadores personalizados en PowerShell, no hay soluciones correctas :

    • Use comandos separados (en líneas separadas o separados por ; ) y pruebe explícitamente el estado de éxito de cada comando a través de la variable automática $? , como:
      command1 -arg1 -arg2; if ($?) { command2 -arg1 } # equivalent of &&
      command1 -arg1 -arg2; if (-not $?) { command2 -arg1 } # equivalent of ||

    • Consulte a continuación la razón por la cual PowerShell -and y -or generalmente no son una solución.

  • Se habló de agregarlos hace un tiempo, pero al parecer nunca llegó a la cima de la lista.

    • Ahora que PowerShell se ha convertido en código abierto, se ha abierto un problema en GitHub .
    • Los tokens && y || actualmente están reservados para su uso futuro en PowerShell, por lo que existe la esperanza de que se pueda implementar la misma syntax que en Bash.
      (A partir de PSv5.1, intentar algo como 1 && 1 produce un mensaje de error The token '&&' is not a valid statement separator in this version. ) The token '&&' is not a valid statement separator in this version.

¿Por qué PowerShell? -and -or no son un sustituto para && y || :

Operadores de control de Bash && (cortocircuito lógico AND) y || (cortocircuito lógico O) verifica implícitamente el estado de éxito de los comandos por sus códigos de salida, sin interferir con sus flujos de salida ; p.ej:

 ls / nosuchfile && echo 'ok' 

Cualquiera que sea la salida, tanto la salida stdout (los archivos en / ) como la salida stderr (el mensaje de error de intentar acceder al archivo nosuchfile archivo nosuchfile ) se pasan , pero && verifica el código de salida (invisible) del comando ls para decidir si se debe ejecutar el comando de echo , el RHS del operador de control && .

En este caso, los informes emiten el código de salida 1 , falla de señalización, porque el archivo nosuchfile no existe, por lo que && decide que ls falló y, al aplicar un cortocircuito, decide que el comando de echo no necesita ejecutarse.
Tenga en cuenta que es el código de salida 0 que señala el éxito en el mundo de cmd.exe y bash , mientras que cualquier código de salida distinto de cero indica un error.

En otras palabras: Bash’s && y || operar de forma completamente independiente de la salida de los comandos y solo actuar sobre el estado de éxito de los comandos.


Los valores de PowerShell -and , por el contrario, actúan solo en la salida estándar (correcta) de los comandos, la consumen y luego solo generan el resultado booleano de la operación ; p.ej:

 (Get-ChildItem \, nosuchfile) -and 'ok' 

Lo anterior:

  • usa y consume la salida de éxito (estándar) – la lista de \ – y la interpreta como un booleano ; una colección de entradas no vacía se considera $true en un contexto booleano, por lo que si hay al menos una entrada, la expresión evalúa $true .

    • Sin embargo, la información de error que resulta del archivo nosuchfile archivo nosuchfile se pasa, porque los errores se envían a una secuencia separada.
  • Dado que Get-ChildItem \, nosuchfile devuelve resultados de salida no vacíos, el LHS se evalúa como $true , entonces -and también evalúa el RHS, 'ok' , pero, de nuevo, consume su salida y lo interpreta como un booleano, que, como una cadena no vacía, también evalúa $true .

  • Por lo tanto, el resultado general de la expresión -and es $true , que es (el único) resultado .

El efecto neto es:

  • El resultado de éxito de ambos lados de la expresión -and se consume durante la evaluación y, por lo tanto, se oculta de manera efectiva .

  • El único resultado (éxito) de la expresión es su resultado booleano , que es $true en este caso (que se representa como True en el terminal en los sistemas de idioma inglés).

Podemos usar el método try catch finally en lugar de usar el método && en powershell.

 try {hostname} catch {echo err} finally {ipconfig /all | findstr bios}