Vous êtes sur la page 1sur 10

PowerShell et les boucles For

I. Présentation
La boucle "For" est un grand classique des différents langages de Scripting et de
programmation. Dans cet article, je vous propose de vous familiariser avec les boucles
"For" en PowerShell.
L'objectif d'une boucle "For" est d'exécuter X fois un bloc d'instructions, où le nombre
d'exécution de l'état de la condition testée.

II. Comment fonctionne une boucle For ?


En PowerShell, la boucle "For" s'appuie sur la syntaxe suivante :
For(<état initial>;<condition de répétition>;<incrémentation>)
{
<Si la condition est vraie, on exécute ce bloc d'instructions>
}

<Si la condition est fausse, la boucle for se termine et le script continue...>


Lorsque l'on utilise une boucle for, on suit la logique suivante : on indique une valeur de
départ (état initial), une valeur cible dans la condition de répétition (par exemple la valeur 10)
et on incrémente la valeur à chaque tour de boucle (à chaque itération) : on peut incrémenter
de 1, de 2, de 10, etc... au choix.

III. Exemples "For" en PowerShell


Pour bien comprendre, c'est toujours mieux d'avoir des exemples, commençons par un
premier exemple très simple. Nous verrons ensuite un autre exemple avec une boucle
"dynamique" et un troisième exemple avec deux conditions.

 Boucle "For" de base


On peut se dire que l'on part de la valeur "1", et que, tant que la valeur est inférieure à 10, on
exécute le bloc d'instruction de la boucle "For", en augmentant de +1 à chaque itération.

Note : Affecter la valeur "0..10" à une variable sert à créer un tableau de valeurs, de 0 à 10.
Ce qui donne :
$valeur = 0..10

For($i=0;$i -lt 10;$i++)


{
Write-Output "La valeur est $($valeur[$i])"
}
Ce qui va donner le résultat suivant :
Cela signifie qu'après la ligne "La valeur est 9", l'exécution du script avec ce poursuivre.
 Boucle "For" basée sur un nombre d'éléments
Imaginons que l'on ait un tableau de chaînes de caractères (string) et que l'on souhaite
exécuter une action sur chaque valeur du tableau, sans connaître à l'avance le nombre
d'éléments du tableau, on peut s'appuyer sur la propriété Length.
On va définir la variable $langages et lui attribuer des valeurs (cela pourrait être dynamique).
Grâce à $langages.Length, nous allons pouvoir faire une boucle qui traite l'ensemble des
éléments du tableau. C'est ce que l'on fait habituellement (et plus simplement) avec une
boucle ForEach mais on peut le faire aussi avec une simple boucle For, d'où cet exemple.
Ce qui donne :
$langages = @("PowerShell","Python","PHP","JavaScript","C-Sharp")

For($i=0;$i -lt $langages.Length;$i++)


{
Write-Output "Le meilleur langage de programmation est $($langages[$i])"
}
Ce qui va donner :

 Boucle "For" à conditions multiple


Au sein d'une boucle "For", on utilise généralement la variable $i pour gérer l'initialisation et
l'incrémentation. Si besoin, on peut utiliser deux conditions afin de créer une boucle For à
conditions multiple. Pour cet exemple, nous prendrons $i et $j. Je mets en jaune les évolutions
au niveau de la syntaxe par rapport à une boucle sur une seule condition.

$valeur = 0..10

For(($i = 0), ($j = 0); $i -lt 10 -and $j -lt 10; $i++,$j++)


{
Write-Output "Les valeurs sont : i = $($valeur[$i]) - j = $($valeur[$j])"
}

Si l'on reprend les deux précédents exemples, avec la valeur de 1 à 10 et le tableau de


langages, cela donne :
$valeur = 0..10

$langages = @("PowerShell","Python","PHP","JavaScript","C-Sharp")

For(($i = 0), ($j = 0); $i -lt 10 -and $j -lt $langages.Length; $i++,$j++)


{
Write-Output "$($valeur[$i]) - $($langages[$i])"
}
Dès que l'on arrive à la fin du tableau $langages, on sort de la boucle "For" car il faut que $i
soit inférieur à 10 ce qui est toujours le cas ET que $j soit inférieur à la longueur du tableau,
ce qui n'est plus le cas car nous sommes au bout du tableau.

Si l'on veut que ça continue jusqu'à la fin de $i et $j, il faut remplacer le "-and" par "-or" pour
que ça continue tant que l'une ou l'autre des conditions soient vraies. Le résultat sera alors
différent :
PowerShell: Boucle Do Until et Do While
I. Présentation
Cette commande PowerShell a pour objectif d’expliquer le fonctionnement des boucles
Do..Until et Do..While en PowerShell, car elles ont un rôle important à jouer dans vos
scripts. Avec une syntaxe très proche voire identique, ces deux boucles ont malgré tout une
logique différente.

II. Do Until avec PowerShell


La boucle Do-Until en PowerShell fonctionne selon la logique suivante :
Do{code} Until(la condition soit vraie)

Autrement dit :
Joue {ce code} Jusqu'à ce que (la condition soit vraie)

Ce qui peut-être intéressant notamment pour vérifier un état dans le" Do" et dès que l'état
attendu arrivera, on sortira de la boucle. Il y a de nombreux cas d'utilisation de ce type de
boucle, ça peut notamment servir de temporisation dans un script pour attendre qu'un état
bascule sur l'état attendu avant de continuer.

Prenons un exemple tout simple, avec une variable $i que l'on va incrémenter de 1 à chaque
fois que l'on rejoue un tour de boucle. On souhaite jouer le code jusqu'à ce que $i soit égal à
10. Voici le code :

$i = 0
Do{

$i++

Write-Host "i = $i"

}Until($i -eq 10)

Write-Host "Boucle terminée !"

Vous verrez que ça marche parfaitement, dès que $i sera égal à 10, on sort de la boucle.

Vous verrez que ça marche parfaitement, dès que $i sera égal à 10, on sort de la boucle.

On peut aussi ajouter plusieurs conditions, admettons que nous avons aussi une variable $j qui
s'incrémente de 1 à chaque tour de boucle... On va initialiser cette variable à 5 alors que $i est
initialisé à 0. On souhaite sortir de la boucle dès que $i ou $j arrive à 10 :
$i = 0

$j = 5

Do{

$i++

$j++
Write-Host "i = $i et j = $j"

}Until(($i -eq 10) -or ($j -eq 10))

Write-Host "Une des deux variables est arrivée à 10 donc on sort de la boucle !"

Vous remarquerez que l'on encadre chaque condition par des parenthèses de la même manière
qu'on peut le faire dans un if, par exemple. De plus, on utilise ensuite l'opérateur -or mais on
pourrait aussi utiliser un autre opérateur tel que -and, selon ce que l'on souhaite faire.

III. Do While avec PowerShell


La boucle Do-While en PowerShell fonctionne à l'inverse de la boucle Do-Until, puisqu'elle
suit la logique suivante :
Do{code} While(la condition est vraie)

Autrement dit :
Joue{ce code} Tant que (la condition est vraie)

Cette boucle est similaire à une boucle classique While, à l'exception de la syntaxe qui sera
différente. Dans le cas de Do While on se dit "Je joue le code tant que la condition est vraie"
alors que dans la boucle While on se dit "Tant que la condition est vraie, je joue". Tout n'est
qu'une question d'ordre dans la syntaxe.

Si l'on voudrait prendre comme exemple, une variable $i qui s'incrémente comme on l'a fait
dans l'exemple du Do-Until, on pourrait mais il faudrait adapter la condition. Car si on
prendre comme condition "$i = 10" ceci veut dire que si on initialise $i à 0, il ne sera pas égal
à 10 alors on va directement quitter la boucle. Pour avoir un équivalent il faut mettre dans la
condition "$i inférieur ou égal à 10".

En français ceci donne :

 Do-Until : Incrémente $i de 1 jusqu'à ce que $i soit égal à 10


 Do-While : Incrémente $i de 1 tant que $i est inférieur ou égal à 10
J'espère que vous avez bien compris la différence.

Prenons un exemple avec le Do-While, où l'on va incrémenter $i de 1 tant qu'il y a un


processus "notepad" (Bloc-notes) en cours d'exécution sur la machine. D'abord, la condition
sera :
Get-Process -Name notepad -ErrorAction SilentlyContinue

On précise le "ErrorAction" en "SilentlyContinue" pour ne pas qu'une erreur s'affiche dans la


console quand le processus sera introuvable c'est à dire quand on aura fermé l'application.
Pour le code de l'exemple, c'est tout simple :
$i = 0

Do{

$i++

Write-Host $i

}While(Get-Process -Name notepad -ErrorAction SilentlyContinue)

Write-Host "Notepad est fermé, on peut continuer !"

On peut voir dans la console que l'on sort de la boucle dès que je ferme le Bloc-notes ouvert
sur ma machine :

Il est à noter que pour ajouter plusieurs conditions dans le Do-While, c'est la même syntaxe
que pour un if ou un Do-Until.
En résumé...
Avec le Do-Until on joue du code jusqu'à ce que la condition soit vraie, c'est à dire
qu'une variable atteigne une valeur spécifique, par exemple, alors qu'avec Do-While on
joue du code tant que la condition est vraie.
PowerShell et les boucles ForEach
I. Présentation
Dans la continuité sur les boucles For en PowerShell, Il est intéressant d'en proposer un
second sur les boucles ForEach car elles sont vraiment indispensables. C'est le type de
boucle qu’on utilise le plus dans les scripts notamment lorsqu'il y a besoin de manipuler une
collection de données. L'avantage c'est que la boucle ForEach va automatiquement traiter
toutes les lignes de notre collection, il n'y a pas besoin de connaître à l'avance le nombre
qu'il y en a, comme c'est le cas avec une boucle For.

II. ForEach - Syntaxe n°1


Dans un script, une boucle Foreach se déclare de façon relativement simple et classique pour
du PowerShell. La syntaxe d'une boucle ForEach est la suivante :
Foreach(<élément> in <collection>)
{
# bloc d'instructions / traitement
}
La collection correspond à notre ensemble de valeurs, représenté par une variable. Il
peut s'agir du contenu d'un fichier CSV, de la liste des processus en cours d'exécution sur
votre PC, du résultat du recherche d'utilisateurs dans l'Active Directory, etc... Tout ce qui
permet de récupérer un ensemble de valeurs.
L'élément correspond à une variable qui va prendre pour valeur chaque objet à traiter
de la collection de données. Par exemple, au premier tour de boucle, l'élément sera notre
première ligne du fichier CSV, au second tour de boucle, ce sera la deuxième, etc... jusqu'à
arriver à la fin du fichier. Cette variable est valide uniquement au sein de la boucle ForEach
pour le traitement interne de la boucle.
Le bloc d'instructions correspond aux actions à réaliser à chaque tour de boucle sur
l'objet en cours de traitement (variable de l'élément). Par exemple, si l'on utilise un fichier
CSV qui contient une liste de nom et prénom, on peut imaginer que l'on va vouloir créer un
utilisateur dans l'Active Directory pour chaque ligne du CSV.
Prenons un exemple : nous allons récupérer la liste des services sur notre PC (Get-Service)
que l'on va stocker dans la variable $collection, et afficher l'état du service, à savoir s'il est
démarré ou arrêté, avec une phrase personnalisée.
$collection = Get-Service

Foreach($element in $collection)
{
"$($element.Name) dans l'état : $($element.Status) ($($element.StartType))"
}
J'ai utilisé les noms $element et $collection pour mes variables, mais vous pouvez utiliser
d'autres noms... Le résultat contiendra le nom du service, son état actuel et son type de
démarrage (manuel ou automatique).
wscsvc dans l'état : Running (Automatic)

WSearch dans l'état : Running (Automatic)

wuauserv dans l'état : Running (Manual)

WwanSvc dans l'état : Stopped (Manual)


XblAuthManager dans l'état : Stopped (Manual)

XblGameSave dans l'état : Stopped (Manual)

XboxGipSvc dans l'état : Stopped (Manual)

XboxNetApiSvc dans l'état : Stopped (Manual)

Nous aurions pu faire la même chose avec cette syntaxe :


Foreach($element in Get-Service)
{
"$($element.Name) dans l'état : $($element.Status) ($($element.StartType))"
}
A chaque itération de la boucle ForEach, la variable $element va prendre un nouvel
objet de notre collection $collection, à savoir un nouveau service. A chaque fois, il est
possible d'accéder aux propriétés de l'objet et à ses méthodes. Ainsi, nous avons pu
facilement récupérer le nom du service via $element.Name, ainsi que son état
avec $element.Status et son type de démarrage avec $element.StartType.
Cette syntaxe est très intéressante et performante puisqu'elle permet de réaliser un ensemble
d'actions sur une collection complète de données chargée au préalable dans une
variable. Attention à la consommation de mémoire sur votre PC puisque l'on va charger
l'intégralité de la collection en mémoire avant traitement.

III. ForEach - Syntaxe n°2


Une autre façon d'utiliser une boucle ForEach plutôt que dans un bloc dans un script, c'est
directement de passer la collection d'objets à traiter à la boucle ForEach au travers d'un
pipeline. Dans ce cas, la boucle ne s'appelle plus ForEach mais Foreach-Object bien que
le mot clé "ForEach" fonctionne toujours, la différence est à signaler.
Pour que ce soit plus simple pour vous de comprendre la différence au niveau de la syntaxe,
reprenons l'exemple précédent. Si l'on s'appuie sur une boucle Foreach-Object, et que l'on
veut reproduire exactement le même résultat que précédemment, la syntaxe est la suivante :
Get-Service | Foreach-Object { "$($_.Name) dans l'état : $($_.Status) ($($_.StartType))" }
Cette syntaxe vu qu'elle tient sur une seule ligne et parfaitement adaptée à la console
PowerShell. La commande Get-Service va envoyer toute sa collection d'objets à la
boucle Foreach-Object qui va traiter chaque objet.
Avec cette syntaxe, nous laissons tomber notre variable $element puisque l'on peut récupérer
directement l'objet en cours avec l'appel de la variable automatique : $_
Bon à savoir : au niveau de la consommation mémoire, l'impact est plus faible qu'avec la
méthode précédente car on traite les objets au fur et à mesure, on ne stocke pas toute la
collection d'objets dans une variable avant de la traiter. Néanmoins, cette méthode est
moins efficace d'un point de vue des performances.
Enfin, il faut savoir qu'à l'instar de la commande Where-Object, la commande Foreach-
Object propose elle aussi une syntaxe simplifiée. Si l'on souhaite afficher seulement un
champ, avec la syntaxe complète on doit écrire :
Get-Service | Foreach-Object { $_.Name }
Avec la syntaxe simplifiée (qui limite les possibilités), cela donne :
Get-Service | Foreach Name
Vous avez désormais connaissance des deux syntaxes possibles pour une boucle ForEach en
PowerShell, avec les avantages et inconvénients de chaque méthode.

Vous aimerez peut-être aussi