Puis-je faire fonctionner «&&» ou «-and» dans PowerShell?

193

&&est notoirement difficile à rechercher sur la recherche Google, mais le meilleur que j'ai trouvé est cet article qui dit à utiliser -and.

Malheureusement, cela ne donne plus d'informations et je ne peux pas savoir ce que je suis censé faire -and(encore une fois, une chose notoirement difficile à rechercher).

Le contexte dans lequel j'essaie de l'utiliser est "exécuter cmd1, et en cas de succès, exécuter cmd2", en gros ceci:

csc /t:exe /out:a.exe SomeFile.cs && a.exe

Si vous souhaitez simplement exécuter plusieurs commandes sur une seule ligne et que vous ne vous souciez pas de savoir si la première échoue ou non, vous pouvez utiliser ;Pour la plupart de mes besoins, cela convient.

Par exemple: kill -n myapp; ./myapp.exe.

Orion Edwards
la source
PowerShell a des opérateurs logiques -et et -or. Les opérateurs ne travaillent pas comme vous l'attendez? Si tel est le cas, vous pouvez publier l'expression ici.
Mohit Chakraborty
Voir cette question, il fait ce que vous voulez: stackoverflow.com/questions/1917271/…
joshperry
3
Quiconque s'intéresse au style Bash &&et ||devient membre de PowerShell: veuillez voter pour la fonctionnalité ici .
mklement0
1
Concernant la nécessité d'effectuer des recherches sur le Web pour les requêtes avec des symboles littéraux (et significatifs): SymbolHound est utile pour cela. Voici quelques exemples relatifs à la question: powershell && ; PowerShell -et . Si vous utilisez DuckDuckGo , vous pouvez rechercher SymbolHound via !sym.
nisavid
3
Mise à jour de juin 2019 : l'équipe PowerShell met en œuvre &&et ||! Pesée au GitHub PR
Pilau

Réponses:

203

Dans CMD, '&&' signifie "exécuter la commande 1, et si elle réussit, exécuter la commande 2". Je l'ai utilisé pour des choses comme:

build && run_tests

Dans PowerShell, la chose la plus proche que vous pouvez faire est:

(build) -and (run_tests)

Il a la même logique, mais le texte de sortie des commandes est perdu. Peut-être que c'est assez bon pour vous, cependant.

Si vous faites cela dans un script, vous ferez probablement mieux de séparer les instructions, comme ceci:

build
if ($?) {
    run_tests
}

2019/11/27 : L' &&opérateur est désormais disponible pour PowerShell 7 Preview 5+ :

PS > echo "Hello!" && echo "World!"
Hello!
World!

Jay Bazuzi
la source
2
RE: "ridicule qu'ils supprimeraient" - Je n'aime pas penser à PowerShell comme "CMD avec les parties stupides enlevées". is.gd/k92B
Jay Bazuzi
103
Je n'aime pas penser à PowerShell comme "CMD avec les parties stupides enlevées". J'aime penser à cela comme "Bash sans aucun des éléments utiles".
Pod
19
Vous pouvez également le faire build ; if ($?) { run_tests }sur la ligne de commande.
docwhat
22
Le moyen le plus rapide de ressentir une réelle frustration lors de l'apprentissage de PowerShell est de commencer par penser qu'il ne s'agit que d'un CMD étendu ou d'une bash. Son modèle est fondamentalement différent, en particulier en ce qui concerne les entrées, les sorties, les tuyauteries et les résultats. Commencez par un bon didacticiel ou un bon aperçu, et n'essayez pas trop de faire fonctionner la syntaxe d'autres shells. Vous devez le prendre selon ses propres termes.
Mark Meuer
4
En utilisant PowerShell selon ses propres conditions, comment exécuter une commande, puis, uniquement si cette commande réussit, exécuter une autre commande? Je ne pense pas que cela impose des bashidées à PowerShell. C'est la fonctionnalité de base du shell. Jusqu'à présent, le meilleur que j'ai vu est celui build ; if ($?) { run_tests }que j'utiliserai à partir de maintenant. J'espère que l'équipe PowerShell ajoute du &&support!
Nate le
29

&& et || étaient sur la liste des choses à implémenter (sont toujours) mais ne sont pas apparues comme la prochaine chose la plus utile à ajouter. La raison en est que nous avons -AND et -OR. Si vous pensez que c'est important, veuillez déposer une suggestion sur Connect et nous la considérerons pour la V3.

Jeffrey Snover - MSFT
la source
11
Je suis inscrit sur Connect et je me suis nominé pour PowerShell, mais je ne sais pas comment placer une suggestion. Le site Web Connect est vraiment complexe et déroutant :-(
Orion Edwards
6
Je n'ai pas trouvé de demande préexistante, alors j'en ai fait une: connect.microsoft.com/PowerShell/feedback/details/778798/…
Andy Arismendi
24
Vous savez, la question est toujours de savoir comment écrire un équivalent, et votre réponse serait beaucoup plus utile si vous -AND
ajoutiez
5
C'est important car c'est un outil de contrôle de flux de base utilisé sur les systèmes plus anciens que Windows pendant presque toute l'éternité. Ainsi est présente ENCORE UNE AUTRE différence de rupture entre Linux et Windows.
airtonix
6
J'espère que Jeffrey Snover écoute, cette SO devrait être une raison suffisante pour l'implémenter maintenant. Cela fait trop longtemps, et maintenant PowerShell commence à apparaître par endroits, comme VSCode l'utilise comme terminal par défaut dans Windows. C'est une douleur totale sans &&, le -andmange la sortie, pas du tout équivalent.
Ciantic
15

Essaye ça:

$errorActionPreference='Stop'; csc /t:exe /out:a.exe SomeFile.cs; a.exe
Ivan
la source
10
Remarque: si la première commande échoue, la seconde est toujours en cours d'exécution.
BrunoLM
4
La variable de préférence $ErrorActionPreferencerégit uniquement la manière dont les erreurs non terminales signalées par les applets de commande sont traitées; les utilitaires externes tels que cscet a.exene signalent jamais de telles erreurs (ils ne reflètent leur état de sortie que dans $?(indicateur de réussite) et $LASTEXITCODE(le code de sortie spécifique signalé)), donc votre ligne de commande équivaut à une exécution inconditionnelle des deux commandes (l'équivalent de cmd's csc /t:exe /out:a.exe SomeFile.cs & a.exe)
mklement0
6

Si votre commande est disponible dans cmd.exe (quelque chose comme python ./script.py, mais pas la commande PowerShell comme ii .(cela signifie ouvrir le répertoire actuel par l' Explorateur Windows )), vous pouvez exécuter cmd.exe dans PowerShell. La syntaxe est la suivante:

cmd /c "command1 && command2"

Ici, &&est fourni par la syntaxe cmd décrite dans cette question .

Tomoyuki Aota
la source
6
Bien, passez à cmd pour accéder à ses fonctionnalités supplémentaires.
Bill K
4

J'ai essayé cette séquence de commandes dans PowerShell:

Premier test

PS C:\> $MyVar = "C:\MyTxt.txt"
PS C:\> ($MyVar -ne $null) -and (Get-Content $MyVar)
True

($MyVar -ne $null)renvoyé vrai et (Get-Content $MyVar)également retourné vrai .

Deuxième test

PS C:\> $MyVar = $null
PS C:\> ($MyVar -ne $null) -and (Get-Content $MyVar)
False

($MyVar -ne $null)renvoyé faux et jusqu'à présent, je dois supposer que le résultat est (Get-Content $MyVar)également faux .

Le troisième test a prouvé que la deuxième condition n'avait même pas été analysée.

PS C:\> ($MyVar -ne $null) -and (Get-Content "C:\MyTxt.txt")
False

($MyVar -ne $null)a renvoyé false et a prouvé que la deuxième condition (Get-Content "C:\MyTxt.txt")n'a jamais été exécutée, en retournant false sur l'ensemble de la commande.

Cleber Machado
la source
Vous avez raison! cela se comporte comme l'opérateur &&. Même un $ () sur le côté droit ne permettra pas d'évaluer cela!
Falco Alexander
2

Question très ancienne, mais pour les nouveaux venus: peut-être que la version PowerShell (similaire mais non équivalente ) que la question recherche, est à utiliser -andcomme suit:

(build_command) -and (run_tests_command)

Francisco Serrano
la source
1
Cela peut convenir à votre cas d'utilisation, mais cela ne se comporte pas comme &&, dans la mesure où il ignore le code de sortie de build_command.
Simon Buchan
Ce n'est certainement pas la bonne chose. Il exécutera la deuxième commande même si la première a échoué.
Nate le
c'est complètement faux. ;est l'équivalent de &en cmd et ;en bash. Ce n'est certainement pas la même chose que &&dans cmd
phuclv
Il coupe également STDOUT et STDERR pour les deux processus.
Dragas
0

Un équivalent verbeux consiste à combiner $LASTEXITCODEet -eq 0:

msbuild.exe args; if ($LASTEXITCODE -eq 0) { echo 'it built'; } else { echo 'it failed'; }

Je ne sais pas pourquoi if ($?)n'a pas fonctionné pour moi, mais celui-ci a fonctionné.

TankorSmash
la source
0

Utilisation:

if (start-process filename1.exe) {} else {start-process filename2.exe}

C'est un peu plus long que "&&", mais il accomplit la même chose sans script et n'est pas trop difficile à retenir.

Lydell Anderson
la source
2
Start-Processest le mauvais outil à utiliser pour appeler les utilitaires de ligne de commande en général. Plus précisément, tel qu'utilisé ici,Start-Process s'exécute de filename1.exemanière asynchrone dans une nouvelle fenêtre de console et ne renvoie rien , ce qui dans un contexte booléen est évalué à $false. Même si vous omettez Start-Process(c'est ainsi que vous devez appeler les utilitaires de ligne de commande - directement), l'approche échouera, car le résultat du conditionnel dépend alors de si l'utilitaire a produit une sortie stdout, ce qui n'a aucune relation garantie avec le fait qu'il réussi ou non.
mklement0
0

Je pense qu'une simple ifdéclaration peut y parvenir. Une fois que j'ai vu la réponse de mkelement0 selon laquelle le dernier statut de sortie est stocké dans $?, J'ai rassemblé les éléments suivants:

# Set the first command to a variable
$a=somecommand

# Temporary variable to store exit status of the last command (since we can't write to "$?")
$test=$?

# Run the test
if ($test=$true) { 2nd-command }

Donc, pour l'exemple du PO, ce serait:

a=(csc /t:exe /out:a.exe SomeFile.cs); $test = $?; if ($test=$true) { a.exe }
slugman
la source
0

Installez simplement PowerShell 7 ( allez ici , faites défiler et développez la section des actifs). Cette version a implémenté les opérateurs de chaîne de pipeline.

Chris
la source
-1

Cela dépend du contexte, mais voici un exemple de "-and" en action:

get-childitem | where-object { $_.Name.StartsWith("f") -and $_.Length -gt 10kb }

Donc, c'est obtenir tous les fichiers de plus de 10 ko dans un répertoire dont le nom de fichier commence par "f".

Matt Hamilton
la source
2
Ce n'est pas une réponse à la question initiale, qui concerne l'exécution de plusieurs commandes.
bdukes
-1

Nous pouvons essayer cette commande au lieu d'utiliser la méthode &&:

try {hostname; if ($lastexitcode -eq 0) {ipconfig /all | findstr /i bios}} catch {echo err} finally {}
Cyberiron
la source
Il n'est pas nécessaire d'utiliser try/ catch, car il n'est nécessaire que pour mettre fin aux erreurs, quels utilitaires externes tels que hostname, ipconfigetfindstr ne peuvent pas déclencher. La vérification $LASTEXITCODEn'est nécessaire que si vous souhaitez connaître le code de sortie spécifique défini par un utilitaire externe - le succès ou l'échec abstrait est reflété $?, tout comme avec les applets de commande natives.
mklement0
Je pense que @Cyberiron est sur la bonne voie. Je pense que &&dans Unix, c'est un peu comme try / catch en ce qu'il ne vous oblige pas à envelopper les commandes suivantes dans un nouveau bloc (c'est-à-dire }) lorsque vous court-circuitez les commandes ultérieures (les sautez). Je pense qu'une AmpAmpfonction / filtre qui jette quand if (!?) { throw "last command failed" }serait un remplacement très utile pour le portage &&vers PowerShell. utilisation :csc /t:exe /out:a.exe SomeFile.cs; AmpAmp; a.exe
yzorg