464 votes

Comment exécuter plusieurs commandes sur une seule ligne dans PowerShell?

Dans une invite de commande, vous pouvez exécuter deux commandes sur une seule ligne comme ceci :

ipconfig /release & ipconfig /renew

Quand j'exécute cette commande dans PowerShell, j'obtiens :

Le symbole & n'est pas autorisé. L'opérateur `&` est réservé pour une utilisation future

Est-ce que PowerShell a un opérateur qui me permet de produire rapidement l'équivalent de & dans une invite de commande ?

N'importe quelle méthode pour exécuter deux commandes sur une seule ligne fera l'affaire. Je sais que je peux créer un script, mais je cherche quelque chose de plus improvisé.

7 votes

Fun Note: Entre les ports série et la sérialisation, cette question est virtuellement impossible à rechercher.

1 votes

Pour être nerd... Il est très facile de le rechercher. C'est juste assez difficile d'obtenir un ensemble de résultats pertinents. :) (+1 pour la super question)

2 votes

665voto

Squeezy Points 8182

Utilisez un point-virgule pour enchaîner les commandes dans PowerShell :

ipconfig /release; ipconfig /renew

15 votes

Vont-ils s'exécuter en parallèle ou séquentiellement ?

28 votes

Cela les exécutera séquentiellement, tout comme l'opérateur & dans cmd.exe.

68 votes

Il y a cependant une grande différence - ";" exécute la seconde commande même si la première échoue.

36voto

user224190 Points 41

Un point-virgule liera les commandes comme l'a indiqué la réponse précédente, bien qu'il y ait une différence clé dans le comportement avec l'opérateur & dans l'interpréteur de commandes de style MS-DOS.

Dans l'interpréteur de commandes, la substitution de variable a lieu lorsque la ligne est lue. Cela permet quelques possibilités intéressantes telles que l'échange de variables sans transition :

set a=1
set b=2
set a=%b% & set b=%a%
echo %a%
echo %b%

Résulterait en :

2
1

Pour autant que je sache, il n'y a pas de moyen de reproduire ce comportement en PowerShell. Certains pourraient dire que c'est une bonne chose.

Il existe en fait un moyen de le faire en PowerShell :

$b, $a = $a, $b

Cela entraînera un échange des valeurs des variables en une seule ligne.

0 votes

Ne semble pas fonctionner à partir du champ "Cible" avec l'option -commande dans le raccourci.

31voto

SimonS Points 7610

En PowerShell 7, nous disposons des opérateurs de chaînage de pipeline qui vous permettent d'ajouter un élément conditionnel à vos commandes en une seule ligne de manière séquentielle

Les opérateurs sont :

  • && ceci exécutera la deuxième commande uniquement si la première réussit.
  • || ceci exécutera la deuxième commande uniquement si la première échoue.

exemples :

PS Z:\Powershell-Scripts> Write-Host "Ceci va réussir" && Write-Host "Donc cela s'exécutera aussi"
Ceci va réussir
Donc cela s'exécutera aussi

PS Z:\Powershell-Scripts> Write-Error "Ceci est une erreur" && Write-Host "Donc cela ne devrait pas s'exécuter"
Write-Error "Ceci est une erreur" && Write-Host "Donc cela ne devrait pas s'exécuter": Ceci est une erreur

PS Z:\Powershell-Scripts> Write-Host "Ceci va réussir" || Write-Host "Cela ne s'exécutera pas"
Ceci va réussir

PS Z:\Powershell-Scripts> Write-Error "Ceci est une erreur" || Write-Host "C'est pourquoi cela s'exécute"
Write-Error "Ceci est une erreur" || Write-Host "C'est pourquoi cela s'exécute": Ceci est une erreur
C'est pourquoi cela s'exécute

bien sûr, vous pouvez les chaîner encore plus ensemble comme x && y || z etc.

cela fonctionne également pour les anciennes commandes de type cmd telles que ipconfig

PS Z:\Powershell-Scripts> ipconfig && Write-Error "abc" || ipconfig

Configuration IP de Windows

    Carte Ethernet Ethernet :

       Suffixe DNS propre à la connexion. . . :
       Adresse IPv6 de liaison locale. . . . .: 
       Adresse IPv4. . . . . . . . . . . . .  :
       Masque de sous-réseau. . . . . . . . . : 255.255.255.0
       Passerelle par défaut. . . . . . . . . : 
ipconfig && Write-Error "abc" || ipconfig: abc

Configuration IP de Windows

    Carte Ethernet Ethernet :

       Suffixe DNS propre à la connexion. . . :
       Adresse IPv6 de liaison locale. . . . .: 
       Adresse IPv4. . . . . . . . . . . . .  :
       Masque de sous-réseau. . . . . . . . . : 255.255.255.0
       Passerelle par défaut. . . . . . . . . : 

Ces opérateurs utilisent les variables $? et $LASTEXITCODE pour déterminer si un pipeline a échoué. Cela vous permet de les utiliser avec des commandes natives et pas seulement avec des cmdlets ou des fonctions.

Source : https://docs.microsoft.com/en-us/powershell/scripting/whats-new/what-s-new-in-powershell-70?view=powershell-7

0 votes

Ne fonctionne pas. J'ai essayé en PowerShell : vagrant destroy -f && vagrant up. Ne fonctionne pas.

1 votes

@BasilA La documentation indique : "Ces opérateurs utilisent les variables $? et $LASTEXITCODE pour déterminer si un pipeline a échoué. Cela vous permet de les utiliser avec des commandes natives et non seulement avec des cmdlets ou des fonctions." donc vous devriez vérifier si vos commandes non natives définissent correctement ces variables

0 votes

D'accord, je vais vérifier cela. Merci.

7voto

Dyllon Gagnier Points 53

Pour PowerShell 5 (installation par défaut pour les machines Windows pour l'avenir prévisible), vous pouvez bien sûr utiliser un point-virgule pour séparer les instructions, mais toutes les instructions seront exécutées par défaut même si l'une échoue. Personnellement, je préfère exécuter les choses de sorte que si une chose échoue, la ligne entière s'arrête dans le REPL et j'imagine que beaucoup d'autres personnes le font aussi.

$ErrorActionPreference vous permet de contrôler le comportement de ce qui se passe lorsqu'une instruction échoue mais est une erreur non terminale (qui sont la plupart des erreurs, y compris les erreurs de commande non trouvée). Vous pouvez définir cette variable $ErrorActionPreference="Stop" afin d'imiter le comportement de && dans Bash et PowerShell 7 pour la portée de cette variable.

$ErrorActionPreference="Stop"
# Saut de ligne
fakeCommand; echo "Here"

J'ai eu du mal à trouver une documentation précise pour ce comportement, mais cette variable semble être dynamiquement délimitée afin que vous puissiez la remplacer temporairement dans un bloc si vous ne souhaitez pas la définir globalement.

Invoke-Command -ScriptBlock {$ErrorActionPreference="Stop"; fakeCommand; echo "Here"}

Enfin, si vous voulez quelque chose de réutilisable, vous pouvez utiliser cette fonction d'ordre supérieur.

function Run-Block-With-Error($block) {
    $ErrorActionPreference="Stop"
    Invoke-Command -ScriptBlock $block
}

Qui est ensuite utilisé comme suit.

Run-Block-With-Error {fakeCommand; echo "Here"}

Notez dans les exemples ci-dessus que "Here" n'est pas imprimé car la commande fakeCommand échoue car ce n'est pas une commande réelle.

J'ai testé le code fourni dans cette solution pour PowerShell 5 et 7 et il devrait être entièrement portable, du moins sur Windows. Bien que PowerShell 7 devrait être très similaire sur différentes plateformes, je n'ai pas testé ces commandes sur Linux ou MacOS.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X