Foreach Statement PowerShell : syntaxe, exemples et bonnes pratiques ⚙️

Utilisateur exécutant une boucle foreach dans PowerShell sur un ordinateur portable.

L’instruction foreach en PowerShell permet de parcourir chaque élément d’une collection déjà chargée en mémoire, comme un tableau ou une liste d’objets, pour exécuter un même bloc d’instructions sur chacun d’eux. Sa syntaxe minimale est simple : foreach ($item in $collection) { }. Exemple concret :

$fruits = "pomme", "banane", "cerise"
foreach ($fruit in $fruits) {
    Write-Output $fruit
}

Ce code affiche successivement chaque valeur du tableau $fruits. Voyons maintenant comment exploiter cette instruction sur des tableaux, des objets, des fichiers, et comment elle se distingue de la cmdlet ForEach-Object et de la méthode .ForEach().

Syntaxe de base de la boucle foreach PowerShell

La structure générale d’une boucle foreach PowerShell repose sur trois éléments : une variable de boucle, une collection PowerShell existante, et un bloc de script exécuté pour chaque itération.

foreach ($variable in $collection) {
    # instructions exécutées pour chaque élément
}

La variable de boucle, ici $variable, prend successivement la valeur de chaque élément de la collection tant que celle-ci n’est pas épuisée. Cette variable reste accessible après la fin de la boucle et conserve la dernière valeur traitée, ce qui distingue cette instruction de certains langages où la portée est strictement limitée au bloc.

Cette instruction fonctionne aussi bien sur un tableau littéral, une variable contenant déjà une collection, ou encore le résultat direct d’une cmdlet placé entre parenthèses. PowerShell charge alors l’ensemble de la collection en mémoire avant de commencer l’itération, contrairement à un pipeline qui traite les objets un par un au fur et à mesure de leur production.

Parcourir un tableau PowerShell

Un tableau PowerShell est l’exemple le plus courant d’utilisation de foreach. Il peut contenir des chaînes, des nombres ou tout autre type d’objet :

$nombres = 1, 2, 3, 4, 5
foreach ($nombre in $nombres) {
    Write-Output ($nombre * 2)
}

Chaque élément du tableau est multiplié par deux et affiché individuellement. Cette approche fonctionne de la même façon quel que soit le type de données stocké dans le tableau.

Parcourir une collection d’objets

PowerShell manipule très souvent des objets plutôt que de simples valeurs, notamment lorsqu’une cmdlet retourne des résultats. La boucle foreach permet d’accéder directement aux propriétés de chaque objet parcouru :

$services = Get-Service
foreach ($service in $services) {
    if ($service.Status -eq "Running") {
        Write-Output "$($service.Name) est actif"
    }
}

Cet exemple parcourt une collection PowerShell de services système et affiche uniquement ceux dont le statut est actif, en combinant la boucle avec une condition.

Lire aussi :  Excel SI contient : la formule pour tester si une cellule contient un mot ou une partie de texte

Utiliser foreach avec des fichiers et des processus

Le même principe s’applique aux fichiers d’un répertoire ou aux processus en cours d’exécution, deux cas fréquents en administration système :

$fichiers = Get-ChildItem -Path "C:\Logs" -Filter "*.log"
foreach ($fichier in $fichiers) {
    Write-Output "$($fichier.Name) - $($fichier.Length) octets"
}

Ici, chaque fichier journal du dossier est listé avec sa taille, ce qui illustre bien l’intérêt de la boucle pour traiter automatiquement un ensemble d’éléments similaires sans dupliquer le code.

Utiliser des conditions et contrôler la boucle avec break et continue

Il est courant de combiner une instruction foreach avec des conditions pour filtrer ou interrompre le traitement. Deux instructions permettent de contrôler précisément le déroulement de la boucle :

  • break interrompt immédiatement la boucle entière, sans traiter les éléments restants.
  • continue ignore uniquement l’itération en cours et passe directement à l’élément suivant.
foreach ($nombre in 1..10) {
    if ($nombre -eq 7) {
        break
    }
    if ($nombre % 2 -eq 0) {
        continue
    }
    Write-Output $nombre
}

Ce script affiche les nombres impairs de 1 à 6, ignore les nombres pairs grâce à continue, puis arrête totalement la boucle dès que la valeur 7 est atteinte grâce à break.

Foreach, ForEach-Object et la méthode .ForEach() : quelles différences

PowerShell propose trois façons distinctes de parcourir une collection, souvent confondues à cause de leur nom proche.

FormeTypeFonctionnementCas d’usage typique
foreachInstruction de langageParcourt une collection déjà chargée en mémoireBoucle classique sur un tableau ou une variable
ForEach-ObjectCmdletTraite chaque objet reçu dans le pipelineChaînage de commandes avec l’opérateur pipe
.ForEach()Méthode de collectionApplique un script block directement sur la collectionÉcriture concise sans variable intermédiaire

L’instruction foreach est en général la plus lisible lorsque la collection est déjà stockée dans une variable. La cmdlet ForEach-Object, elle, s’intègre naturellement dans un pipeline, en recevant les objets à mesure qu’ils sont produits par la commande précédente, sans devoir attendre que toute la collection soit chargée.

Utiliser ForEach-Object et la variable $_

Avec ForEach-Object, chaque objet du pipeline est représenté par la variable automatique $_, aussi appelée $PSItem. Ces deux notations sont strictement équivalentes :

Get-Process | ForEach-Object {
    Write-Output "$($_.Name) utilise $($_.CPU) secondes CPU"
}

Ce script block s’exécute pour chaque processus transmis dans le pipeline. $_ remplace ici la variable explicite qu’on aurait déclarée avec une instruction foreach classique, comme $item dans les exemples précédents.

Lire aussi :  Ouvrir un fichier CSV avec Excel : la méthode fiable pour bien répartir les données en colonnes

La méthode .ForEach() sur une collection

Depuis PowerShell 4.0, une collection dispose directement d’une méthode .ForEach(), qui applique un script block sans passer par le pipeline ni par une instruction séparée :

$fruits = "pomme", "banane", "cerise"
$fruits.ForEach({ Write-Output $_.ToUpper() })

Cette syntaxe reste proche de ForEach-Object dans son usage de $_, mais s’exécute directement sur la collection déjà en mémoire, sans transiter par le pipeline, ce qui la rapproche davantage du fonctionnement de l’instruction foreach.

Choisir entre boucle classique et pipeline

Le choix entre foreach et ForEach-Object dépend surtout du contexte du script. foreach convient bien lorsque la collection est déjà disponible dans une variable et que la lisibilité prime. ForEach-Object devient pertinent dès que la boucle s’insère dans une chaîne de commandes avec l’opérateur pipe, en traitant les objets au fil de l’eau plutôt qu’après un chargement complet en mémoire.

Get-ChildItem -Path "C:\Data" | Where-Object { $_.Length -gt 1MB } | ForEach-Object {
    Write-Output $_.Name
}

Dans cet exemple, l’usage de ForEach-Object s’intègre naturellement après un filtre Where-Object, ce qu’une instruction foreach classique rendrait plus lourd à écrire.

Erreurs fréquentes avec l’instruction foreach

Certaines erreurs reviennent régulièrement chez les débutants comme chez les utilisateurs plus expérimentés :

  • Confondre foreach et ForEach-Object : écrire $collection | foreach ($item in $collection) produit une erreur de syntaxe, car l’instruction foreach ne s’utilise pas avec le pipeline de cette manière.
  • Utiliser $_ dans une instruction foreach classique : $_ n’existe que dans un script block de pipeline, pas dans le bloc d’une instruction foreach, où seule la variable déclarée après foreach ( est disponible.
  • Modifier la collection pendant son parcours : ajouter ou supprimer un élément d’un tableau en cours de boucle peut provoquer des comportements imprévisibles.
  • Oublier que la variable de boucle persiste après la boucle : réutiliser un nom de variable de boucle ailleurs dans le script sans le réinitialiser peut introduire des bugs silencieux.
  • Confondre script block et bloc de l’instruction foreach : le contenu entre accolades d’une instruction foreach n’est pas un script block indépendant comme celui utilisé avec ForEach-Object ou .ForEach() ; il ne peut pas être stocké dans une variable puis réutilisé de la même manière.

Bonnes pratiques pour écrire des boucles foreach lisibles

Nommer explicitement la variable de boucle selon son contenu, plutôt que d’utiliser systématiquement $item, améliore nettement la lisibilité d’un script long. Il est également conseillé de limiter la profondeur des blocs imbriqués et de préférer une condition claire à une suite de vérifications empilées dans une même itération. Pour les traitements plus complexes impliquant de nombreux objets et des besoins avancés comme l’exécution simultanée de plusieurs itérations, ForEach-Object -Parallel existe dans les versions récentes de PowerShell, mais reste une option à réserver à des cas spécifiques plutôt qu’un usage systématique.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *