PowerShell foreach : syntaxe, tableaux, CSV et exemples pratiques

En PowerShell, le choix de la boucle dépend surtout de la forme des données à traiter. Pour parcourir un tableau déjà chargé en mémoire, l’instruction foreach reste généralement la plus lisible. Pour exploiter les objets

Written by: François Lestienne

Published on: octobre 5, 2026


En PowerShell, le choix de la boucle dépend surtout de la forme des données à traiter. Pour parcourir un tableau déjà chargé en mémoire, l’instruction foreach reste généralement la plus lisible. Pour exploiter les objets qui arrivent depuis une commande, ForEach-Object s’intègre au pipeline. Et lorsqu’un traitement porte sur des fichiers CSV, la boucle n’est souvent qu’une partie du travail : il faut aussi contrôler les colonnes, les valeurs et le format d’exportation.

Dans une petite équipe informatique, ces différences se voient vite. Un administrateur qui vérifie une liste de serveurs n’a pas les mêmes contraintes qu’un script qui examine des milliers de fichiers ou importe des comptes depuis un tableau fourni par les ressources humaines. Voici comment choisir la bonne syntaxe foreach, éviter les pièges courants et garder un traitement de données compréhensible, même plusieurs mois après son écriture.

En bref

  • foreach parcourt une collection disponible en mémoire et convient bien aux tableaux PowerShell.
  • ForEach-Object traite les éléments transmis par le pipeline, un à un.
  • Import-Csv et Export-Csv facilitent l’importation CSV et l’exportation CSV d’objets PowerShell.
  • La parallélisation avec -Parallel nécessite PowerShell 7 ou une version ultérieure et ne convient pas à tous les traitements.

Comprendre la boucle foreach et choisir la bonne variante PowerShell

La boucle foreach exécute un bloc de commandes pour chaque élément d’une collection. À chaque passage, une variable temporaire reçoit l’élément courant. Le principe est simple : une liste d’ordinateurs, de services ou de fichiers fournit les valeurs, et le bloc applique à chacune la même vérification ou la même action.

La forme classique s’écrit ainsi : foreach ($element in $collection) { … }. La variable placée avant in est choisie par le script. Il est préférable de lui donner un nom qui décrit son contenu, comme $serveur ou $fichier, plutôt que $x. Ce petit choix rend les conditions plus faciles à relire quand le script grossit.

PowerShell propose aussi la cmdlet ForEach-Object. Elle reçoit les objets depuis le pipeline et exécute un bloc pour chacun. Cette approche s’accorde naturellement avec une commande comme Get-Process ou Get-ChildItem. La troisième option est la méthode .ForEach(), disponible sur les collections compatibles. Elle peut être concise, mais sa syntaxe n’est pas toujours aussi évidente pour une équipe qui reprend le script.

Approche Fonctionnement Cas d’usage courant
Instruction foreach Parcourt une collection déjà obtenue. Tableau de serveurs ou de comptes.
ForEach-Object Traite les objets du pipeline au fil de leur arrivée. Résultats d’une commande ou flux volumineux.
Méthode .ForEach() Applique un bloc à une collection compatible. Traitement compact d’une collection en mémoire.

Ces formes ne sont pas des synonymes interchangeables. L’instruction foreach convient aux collections déjà constituées et permet de lire tout le parcours dans un même bloc. ForEach-Object évite de devoir construire une seconde liste uniquement pour appliquer une action à chaque résultat, mais la cmdlet ajoute un coût de traitement. Sur quelques dizaines d’éléments, la différence est rarement le sujet ; sur des volumes importants, il faut mesurer plutôt que supposer.

Dans une PME fictive, Atelier Nord conserve les noms de ses serveurs dans un tableau pour vérifier leur disponibilité. La liste est courte, stable et connue avant l’exécution : l’instruction foreach est un choix naturel. À l’inverse, une commande qui récupère les fichiers d’un partage peut alimenter ForEach-Object directement, surtout si le répertoire contient de nombreux éléments.

Un détail mérite d’être clarifié : dire que le pipeline traite les objets au fil de l’eau ne signifie pas que toute commande en amont produit nécessairement ses résultats sans en charger aucun. Le comportement dépend aussi de cette commande. Le bon réflexe consiste à examiner l’ensemble du pipeline, pas seulement la boucle finale. Le choix utile est celui qui correspond au flux réel des données et qui reste lisible pour la personne chargée de maintenir le script.

Syntaxe foreach et tableaux PowerShell : parcourir une collection proprement

Les tableaux PowerShell regroupent plusieurs valeurs sous une même variable. Ils peuvent contenir des chaînes, des nombres ou des objets issus de commandes. Pour parcourir un tableau, l’instruction foreach affecte successivement chaque valeur à la variable déclarée dans la boucle. Il n’est pas nécessaire de créer cette variable au préalable.

A lire également :  Clés Windows 7 : types, usages et où les obtenir légalement

Un exemple simple permet de vérifier le mécanisme : $nombres = 1, 2, 3, 4, 5, puis foreach ($nombre in $nombres) { Write-Output « Valeur : $nombre » }. À chaque tour, le script affiche une valeur différente. Dans un cas concret, la même structure peut contrôler une liste de noms de machines, comparer des chemins ou appliquer une règle à plusieurs objets.

Voici un exemple avec des ordinateurs : $serveurs = @(« SRV-FICHIERS », « SRV-AD », « SRV-SAUVEGARDE »). La boucle peut ensuite vérifier une propriété ou appeler une fonction de contrôle pour chaque nom. L’opérateur @() permet de rendre explicite la création d’un tableau, notamment lorsque le résultat pourrait ne contenir qu’un seul élément.

Les résultats de commandes peuvent eux aussi être parcourus. Par exemple, Get-ChildItem -Path « C:Logs » -File renvoie des objets fichier. Une boucle foreach peut reprendre ces objets et accéder à leurs propriétés avec la notation pointée : $fichier.Name, $fichier.Length ou $fichier.LastWriteTime. PowerShell travaille ici avec des objets structurés, pas seulement avec des lignes de texte.

découvrez la boucle foreach en powershell : syntaxe, parcours de tableaux et de fichiers csv, avec des exemples pratiques pour automatiser vos scripts.

Une condition intégrée au bloc permet de ne traiter que certains éléments. Par exemple, un script peut afficher les fichiers de plus de 100 Ko en testant $fichier.Length -gt 102400. Pour une opération de nettoyage, il est prudent de séparer d’abord la sélection de la suppression : afficher les chemins concernés, vérifier le résultat, puis seulement lancer l’action destructive. Une erreur de chemin dans une boucle transforme rapidement une tâche répétitive en incident.

Les instructions break et continue modifient le parcours. continue passe directement à l’élément suivant, utile lorsqu’un élément ne respecte pas les critères. break quitte complètement la boucle, par exemple quand une recherche a trouvé la valeur attendue. Elles doivent rester visibles dans le code : un break placé dans une boucle imbriquée peut rendre le flux moins évident à suivre.

Il vaut mieux éviter de modifier la collection parcourue dans le même bloc. Supprimer des éléments d’une liste pendant son énumération peut produire des résultats inattendus ou une erreur. Une méthode plus sûre consiste à construire une liste des éléments à retirer, puis à réaliser la suppression dans une étape séparée. Pour les tableaux simples, cette séparation clarifie aussi la logique de contrôle.

Enfin, les tableaux sont pratiques, mais ils ne règlent pas toutes les questions de performance. Construire une grande collection avant de commencer le parcours consomme de la mémoire. Pour quelques centaines de noms d’hôtes, ce n’est généralement pas un problème ; pour une collecte importante, il faut considérer la façon dont les données sont produites et envisager un traitement par pipeline. La syntaxe n’est qu’une partie du choix : la taille et l’origine de la collection comptent tout autant.

Importation CSV et exportation CSV avec une boucle PowerShell

Un fichier CSV sert souvent de passerelle entre PowerShell et un outil métier. Il peut contenir des noms de comptes, des machines à contrôler ou des paramètres de configuration. Avec Import-Csv, chaque ligne devient un objet dont les en-têtes de colonnes deviennent des propriétés. La boucle peut alors traiter ces valeurs sans découper manuellement chaque ligne à la virgule.

Supposons qu’un fichier serveurs.csv contienne les colonnes Nom et Environnement. L’importation peut être écrite ainsi : $serveurs = Import-Csv -Path « .serveurs.csv » -Delimiter « ; ». Le séparateur doit correspondre au fichier réel. Dans certains exports francophones, le point-virgule est utilisé à la place de la virgule, notamment lorsque la virgule sert de séparateur décimal dans un tableur.

Le traitement peut ensuite parcourir les objets importés : foreach ($serveur in $serveurs) { Write-Output « $($serveur.Nom) : $($serveur.Environnement) » }. La syntaxe $() permet d’insérer une expression dans une chaîne de caractères. Si l’en-tête contient des espaces ou des caractères particuliers, il peut être nécessaire d’utiliser une référence de propriété entre accolades, par exemple $serveur.’Nom du serveur’.

Avant d’automatiser une modification de comptes ou de machines, vérifiez le contenu du fichier. Un en-tête mal orthographié, une cellule vide ou un encodage inattendu peut conduire à des propriétés absentes. Un contrôle simple permet de rejeter les lignes incomplètes plutôt que de transmettre silencieusement une valeur vide à une commande sensible.

Dans Atelier Nord, la liste des nouveaux postes peut inclure un nom, un service et un site. Le script peut vérifier que ces trois colonnes sont présentes et que le nom n’est pas vide avant d’effectuer la moindre opération. Pour une importation liée à Active Directory, le module nécessaire et les droits adéquats doivent également être disponibles. Le CSV ne doit pas contenir de mots de passe en clair : un fichier partagé ou conservé trop longtemps devient une exposition inutile.

A lire également :  Mot de passe Windows 7 perdu : quelles solutions pour retrouver l’accès ?

Pour produire un nouveau fichier, Export-Csv sérialise les objets et leurs propriétés : $resultats | Export-Csv -Path « .controle.csv » -NoTypeInformation -Encoding utf8. Le paramètre -NoTypeInformation évite l’ajout d’une ligne décrivant le type d’objet, un comportement rencontré notamment dans Windows PowerShell 5.1. PowerShell 7 ne l’ajoute pas par défaut, mais le paramètre reste accepté et peut rendre l’intention du script explicite.

Il est préférable d’exporter des objets possédant des propriétés nommées, plutôt que de fabriquer des chaînes séparées par des virgules. Avec [pscustomobject], un script peut produire une structure propre : [pscustomobject]@{ Nom = $serveur.Nom; Statut = « Vérifié » }. Cette approche conserve des colonnes cohérentes et facilite la réutilisation du résultat dans une autre commande PowerShell.

Attention à ne pas confondre CSV et format de sauvegarde PowerShell. Export-Csv est pratique pour l’échange et l’analyse dans un tableur, mais il ne préserve pas toujours le type précis des valeurs comme le ferait un format conçu pour les objets PowerShell. Pour transmettre des résultats à une équipe, c’est souvent le bon outil ; pour restaurer fidèlement des objets complexes, il faut choisir un mécanisme adapté à cet objectif.

ForEach-Object, pipeline et traitement de données volumineuses

ForEach-Object intervient lorsqu’une commande produit des objets qu’il faut traiter sans écrire une boucle classique autour du résultat. Sa forme la plus courante est Get-Process | ForEach-Object { … }. Dans le bloc, la variable automatique $_ représente l’objet courant. L’alias % existe, mais dans un script partagé, écrire le nom complet de la cmdlet facilite la lecture.

Par exemple, les fichiers d’un dossier peuvent être affichés avec leur taille : Get-ChildItem -Path « C:Logs » -File | ForEach-Object { Write-Output « $($_.Name) : $($_.Length) octets » }. Cette construction traite les objets transmis par le pipeline. Elle évite de nommer une variable de boucle, mais impose de comprendre le contexte de $_, surtout lorsque le script contient plusieurs pipelines ou des blocs imbriqués.

ForEach-Object accepte aussi les blocs Begin, Process et End. Begin s’exécute une fois avant le traitement, Process une fois par objet reçu, et End une fois après le dernier objet. Cette séparation est utile pour initialiser un compteur, traiter les éléments et produire un bilan. Elle ne rend pas automatiquement le script plus rapide ; elle donne surtout une structure adaptée aux traitements en flux.

Un exemple de rapport peut compter les fichiers examinés. Dans le bloc Begin, le compteur est initialisé ; dans Process, il augmente pour chaque fichier ; dans End, le nombre final est affiché. Si le bloc Process contient une opération coûteuse, il devient plus facile de distinguer le coût par élément de celui de l’initialisation ou du rapport final.

Pour des opérations réseau indépendantes, PowerShell 7 permet d’utiliser ForEach-Object -Parallel. Un exemple schématique est $serveurs | ForEach-Object -Parallel { Test-Connection -ComputerName $_ -Count 1 } -ThrottleLimit 5. Le paramètre -ThrottleLimit limite le nombre de traitements simultanés. Dans cette configuration, cinq blocs peuvent travailler en parallèle, mais cette valeur doit être choisie selon la machine, le réseau et la charge imposée aux systèmes distants.

Les variables définies à l’extérieur du bloc parallèle ne sont pas visibles comme des variables locales ordinaires. Le modificateur $using: permet de transmettre une valeur, par exemple $using:delai. Il ne faut pas en déduire qu’une variable partagée peut être modifiée sans précaution : plusieurs traitements concurrents peuvent tenter d’écrire au même endroit en même temps.

La parallélisation est surtout utile lorsque chaque tâche attend une réponse, comme un appel réseau ou une requête distante. Pour un bloc minuscule qui transforme une chaîne, la création et la gestion des espaces d’exécution peuvent coûter plus cher que le travail lui-même. Mesurer avec Measure-Command aide à vérifier le gain dans le contexte réel, avec des données représentatives et un environnement comparable.

Il faut aussi tenir compte des effets de bord. Deux blocs parallèles ne devraient pas modifier simultanément le même fichier de sortie ou une collection ordinaire partagée. Pour collecter des résultats concurrents, une structure thread-safe peut être nécessaire, mais elle ajoute de la complexité. Dans beaucoup de scripts d’administration, une boucle séquentielle fiable vaut mieux qu’une accélération difficile à diagnostiquer.

Bonnes pratiques, erreurs fréquentes et contrôle des scripts foreach

Un script de boucle doit rester facile à relire avant d’être rapide. Des noms précis comme $utilisateur, $ligneCsv ou $fichierJournal donnent immédiatement le rôle de chaque valeur. Dans une équipe, cette clarté compte davantage qu’un raccourci d’une ligne, surtout lorsqu’un script intervient sur des comptes ou des serveurs de production.

A lire également :  Dockerfile Windows : exemples, syntaxe et bonnes pratiques

Privilégiez Write-Output ou la production directe d’objets lorsque le résultat doit être redirigé ou chaîné. Write-Host sert à afficher un message à l’écran, mais ne se comporte pas comme une sortie de données destinée au pipeline. Mélanger les deux sans intention claire complique la réutilisation du script.

Les opérations qui peuvent échouer doivent être encadrées par une gestion d’erreurs adaptée. Un accès réseau, une suppression ou une création de compte ne mérite pas d’être traité comme une simple conversion de chaîne. Un bloc try/catch peut isoler l’échec d’un élément et permettre au traitement de continuer, à condition de journaliser clairement l’objet concerné et la raison de l’échec.

Avant toute action de suppression ou de modification en lot, prévoyez un mode de vérification. Pour Remove-Item, le paramètre -WhatIf permet de voir les actions prévues sans les exécuter. Ce contrôle est particulièrement utile lors d’un nettoyage de fichiers anciens. Il ne remplace pas une sauvegarde, mais il révèle souvent une erreur de filtre ou de chemin avant qu’elle ne touche les données.

Un filtre appliqué avant la boucle réduit le travail inutile. Pour ne retenir que les fichiers qui correspondent à une condition, les cmdlets de filtrage comme Where-Object peuvent précéder ForEach-Object. Pour une commande qui propose un filtre natif, mieux vaut souvent l’utiliser : un filtrage effectué à la source évite de transmettre des objets qui seront immédiatement écartés.

Voici quelques vérifications utiles avant de déployer un script sur plusieurs machines :

  • Confirmer que la collection ou le fichier CSV contient les colonnes attendues.
  • Tester le parcours sur un petit échantillon et afficher les actions prévues.
  • Vérifier les chemins, les droits et les paramètres régionaux du fichier.
  • Conserver un journal exploitable des erreurs et des objets traités.
  • Mesurer les performances avant d’ajouter une exécution parallèle.

Les blocs de traitement trop longs sont un autre signal à surveiller. Quand une boucle contient plusieurs étapes métier, déplacer le traitement dans une fonction nommée clarifie son rôle et simplifie les tests. La boucle se contente alors de parcourir les éléments et d’appeler la fonction, au lieu de mélanger sélection, validation, modification et rapport dans un seul bloc.

Enfin, les alias et les raccourcis ont leur place dans une console interactive, mais les scripts maintenus sur la durée gagnent à employer les noms explicites des commandes. ForEach-Object est plus lisible que son alias, et une variable descriptive explique mieux le traitement que $_ dans une expression complexe. La meilleure boucle est celle dont le comportement reste évident quand un collègue doit intervenir dans l’urgence.

Choisir la syntaxe foreach adaptée à chaque tâche

Pour parcourir un tableau déjà chargé, l’instruction foreach constitue généralement le choix le plus direct. Pour une sortie de commande traitée dans le pipeline, ForEach-Object s’intègre mieux au flux. La méthode .ForEach() peut convenir à une collection déjà en mémoire, mais elle ne devrait pas être choisie uniquement parce qu’elle tient sur une ligne.

Avec les fichiers CSV, le vrai travail commence avant la boucle : confirmer le séparateur, contrôler les en-têtes, repérer les valeurs manquantes et décider quelles colonnes seront exportées. Une importation correcte produit des objets exploitables ; une exportation bien préparée fournit un fichier réutilisable sans devoir réparer sa structure dans un tableur.

La parallélisation répond à un besoin différent. Elle peut réduire l’attente sur des appels indépendants, mais elle ne compense ni un mauvais filtrage ni une collection inutilement volumineuse. Dans les scripts d’administration, la prévisibilité et la traçabilité passent avant quelques secondes gagnées, surtout lorsque les actions touchent à l’annuaire, aux fichiers ou à des machines distantes.

Sur un poste de test, commencez par un petit tableau, puis remplacez-le par les données réelles une fois les sorties vérifiées. Cette progression permet de valider les conditions et les chemins sans exposer tout un parc à une première version du script. Gardez les opérations destructrices désactivées tant que le résultat de contrôle n’est pas conforme.

Quelle différence entre foreach et ForEach-Object dans PowerShell ?

L’instruction foreach parcourt une collection déjà disponible dans une variable. ForEach-Object traite les objets reçus par le pipeline, ce qui convient bien aux résultats de commandes et aux flux.

Comment parcourir un tableau PowerShell ?

Utilisez la forme foreach ($element in $tableau) { … }. Donnez à la variable un nom qui décrit son contenu pour rendre le bloc plus facile à maintenir.

Comment traiter des fichiers CSV avec PowerShell ?

Import-Csv transforme les lignes du fichier en objets. Vérifiez le séparateur et les en-têtes, puis parcourez les objets avec foreach ou ForEach-Object. Export-Csv permet d’écrire les résultats structurés dans un nouveau fichier.

Le paramètre -Parallel est-il disponible dans toutes les versions de PowerShell ?

Non. ForEach-Object -Parallel est disponible à partir de PowerShell 7. Il faut aussi tenir compte des accès concurrents et mesurer le gain avant de l’utiliser en production.

Laisser un commentaire

Précédent

Commandes PowerShell essentielles : liste pratique pour Windows 10 et 11