PowerShell each : Maîtrisez les boucles ForEach

Idées principalesDétails
🔄 Trois variantes de boucleInstruction foreach, cmdlet ForEach-Object, méthode .ForEach().
📦 Instruction foreachCharger toute la collection en mémoire, syntaxe classique et très lisible.
⚙️ Cmdlet ForEach-ObjectTraiter les objets au fil du pipeline, réduire consommation mémoire sur gros volumes.
🧩 Méthode .ForEach()Disponible depuis PowerShell 5, concise et permettant le chaînage sur collections.
⚡ Parallélisation avec -ParallelExécuter plusieurs scriptblocks simultanément, utiliser modificateur Using :.
🎯 Bonnes pratiquesNommer explicitement les variables, préférer Write-Output, conserver boucles concises.

PowerShell gère aujourd’hui des milliers de scripts d’automatisation dans les environnements Windows professionnels, et la boucle ForEach figure parmi les constructions les plus utilisées de tout l’écosystème.

Comprendre ses variantes, c’est gagner un temps considérable sur des tâches répétitives qui, sinon, prendraient des heures manuellement. Je vous suggère un tour complet de la question, du débutant au pro.

🔄 Foreach en PowerShell : Trois variantes, une seule logique

Beaucoup confondent les différentes formes de boucle disponibles dans PowerShell. Pourtant, il en existe trois bien distinctes, chacune adaptée à un contexte précis. Voici un tableau comparatif pour y voir clair :

VarianteIntroductionContexte idéal
🗂️ Instruction foreachWindows PowerShell (dès le début)Collections chargées en mémoire, scripts lisibles
⚙️ Cmdlet ForEach-ObjectWindows PowerShellPipeline, traitement flux par flux, économie mémoire
🧩 Méthode .ForEach()PowerShell 5Tableaux, listes, chaînage de méthodes orienté objet

L’instruction foreach utilise la syntaxe classique foreach ($item in $collection) { ... }. PowerShell crée automatiquement la variable d’itération, charge toute la collection en mémoire, puis exécute le bloc de code pour chaque élément. C’est la forme la plus lisible, impeccable pour parcourir un tableau de noms de fichiers ou une liste de serveurs.

La cmdlet ForEach-Object, quant à elle, fonctionne dans le pipeline. Plutôt que de tout charger d’un coup, elle traite chaque objet au fil de son arrivée, ce qui réduit considérablement la consommation mémoire sur de gros volumes de données. Elle accepte les alias % et foreach, pratiques pour les one-liners. Avec PowerShell 3.0, une syntaxe simplifiée a été introduite pour accéder directement à une propriété ou une méthode sans scriptblock total, par exemple Get-Process | ForEach-Object Name.

La méthode .ForEach(), disponible depuis PowerShell 5, s’utilise directement sur un objet collection. Elle est plus concise et permet le chaînage, mais reste limitée aux types compatibles comme les tableaux et les listes. Pour des astuces sur les outils système et les scripts OS, ce genre de subtilité fait toute la différence en pratique.

💡 Syntaxe concrète et exemples d’itération courants

Passons aux choses sérieuses. Voici un exemple basique d’itération sur un tableau de nombres :

$nombres = 1, 2, 3, 4, 5
foreach ($n in $nombres) {
    Write-Output "Valeur : $n"
}

Simple, lisible, efficace. Pour parcourir tous les fichiers d’un répertoire et afficher leur taille, l’approche pipeline avec ForEach-Object est plus adaptée :

Get-ChildItem -Path "C :\Logs" | ForEach-Object {
    Write-Output "$($.Name) : $($.Length) octets"
}

La variable $_ représente l’objet courant dans le pipeline. C’est un réflexe à acquérir absolument. Les blocs -Begin et -End permettent d’exécuter du code une seule fois avant ou après le traitement, utile pour initialiser un compteur ou écrire un rapport final.

Les cas d’usage ne manquent pas. Renommer des fichiers en masse, modifier une clé de registre, analyser des journaux événements, créer des sauvegardes de fichiers de configuration… Autant de tâches où la boucle foreach transforme un travail de deux heures en script de dix lignes. Franchement, je ne m’en lasse pas ! 😄

  • 🗃️ Itérer sur un tableau pour afficher ou transformer des valeurs
  • 📁 Parcourir les fichiers d’un dossier avec Get-ChildItem
  • 🔧 Modifier des propriétés d’objets système en lot
  • 📊 Exporter des données structurées via Export-Csv
  • 🔍 Combiner avec Where-Object pour filtrer avant d’itérer

⚡ ForEach-Object -Parallel : Puissance et pièges à éviter

PowerShell 7.0 a introduit le paramètre -Parallel pour ForEach-Object, permettant d’exécuter plusieurs scriptblocks simultanément sur des threads distincts. La taille du pool de runspaces est fixée à 5 par défaut, ajustable via -ThrottleLimit. Depuis PowerShell 7.1, ces instances sont réutilisées entre les itérations, ce qui améliore les performances globales. Le paramètre -UseNewRunspace force la création d’un runspace neuf à chaque itération si l’isolation est critique.

Pour passer une variable externe dans un scriptblock parallèle, le modificateur Using : est indispensable. Sans lui, le thread enfant n’a aucun accès aux variables du thread appelant. Si vous devez modifier un objet partagé entre threads, utilisez impérativement des types thread-sûrs comme ceux du namespace System.Collections.Concurrent du .NET, sous peine de résultats imprévisibles.

La parallélisation n’est pas toujours la bonne réponse. Pour des opérations triviales, la surcharge de création de runspaces peut rendre le script plus lent qu’une exécution séquentielle. Elle brille sur des traitements intensifs en calcul ou des opérations d’entrée/sortie longues, comme des appels réseau ou des lectures de fichiers volumeux. Pensez-y comme à un turbo : utile sur autoroute, inutile en ville.

Parmi les erreurs classiques à éviter absolument : réutiliser le même nom de variable dans des boucles imbriquées (source de bugs vicieux), modifier la collection pendant qu’on l’itère (boucle infinie garantie), ou sortir prématurément avec break dans un contexte where ce n’est pas prévu. Pour les environnements professionnels gérant des flottes de machines, des plateformes comme Kaseya 365 exploitent cette scriptabilité à grande échelle via PowerShell.

🚀 Aller plus loin : Bonnes pratiques et automatisation avancée

La lisibilité d’un script ForEach fait toute la différence sur le long terme. J’insiste sur l’utilisation de noms de variables explicites plutôt que des noms génériques comme $x ou $tmp. Un $serveurName se comprend au premier coup d’oeil, six mois après l’écriture du script.

Évitez Write-Host : il bloque toute redirection de sortie. Préférez Write-Output, qui s’intègre naturellement dans le pipeline et permet d’exporter proprement vers un fichier ou une autre cmdlet. Sur des machines qui ont connu des manipulations système notables, il peut arriver qu’un guide de réinitialisation Windows soit nécessaire avant de retrouver un environnement PowerShell sain.

Comment réinitialiser votre PC : guide complet pour restaurer Windows à l'état d'usine

Gardez le corps de chaque boucle aussi concis que possible. Si la logique dépasse une dizaine de lignes, déplacez-la dans une fonction dédiée appelée depuis la boucle. Vos collègues (et votre futur moi) vous remercieront. L’automatisation des tâches répétitives reste la vraie valeur ajoutée de PowerShell, et la boucle ForEach en est le moteur central.

Notre partenaire
Gamerz Voice
Logo