PowerShell each : MaĂźtrisez les boucles

| Idées principales | Détails et application |
|---|---|
| đ Trois mĂ©thodes d’itĂ©ration | Comparer foreach, ForEach-Object et .ForEach() pour choisir l’optimale. |
| ⥠Foreach charge la collection | Rapide pour petites collections, gourmand en mémoire pour gros volumes de données. |
| đ ForEach-Object traite au pipeline | Traiter objet par objet sans charger l’intĂ©gralitĂ© en mĂ©moire, idĂ©al gros flux. |
| đ .ForEach() surpasse les autres | MĂ©thode PowerShell 4+ trĂšs performante pour collections dĂ©jĂ chargĂ©es. |
| đ Filtrer fichiers par date | Supprimer fichiers non modifiĂ©s depuis 7 jours avec conditions simples. |
| đ„ CrĂ©er utilisateurs en masse | Automatiser Active Directory avec boucles et blocs Try-Catch robustes. |
| âïž ParallĂ©lisation disponible | ParamĂštre -Parallel depuis PowerShell 7, jusqu’Ă 5 exĂ©cutions simultanĂ©es. |
| đ SĂ©curiser les donnĂ©es parallĂšles | Utiliser ConcurrentDictionary pour gĂ©rer accĂšs concurrents sans conflits. |
Vingt ans que je tape des scripts, et je peux vous dire que la boucle foreach en PowerShell reste l’une des constructions les plus utilisĂ©es au quotidien.
Supprimer des fichiers vieux de plus de 7 jours, crĂ©er des comptes en masse dans Active Directory, filtrer des parcours qui dĂ©passent 400 Mo de mĂ©moire… tout ça, c’est du foreach. Voici un guide concret pour maĂźtriser ça du premier coup.
đ Foreach, ForEach-Object et .ForEach() : Trois outils, trois logiques
PowerShell propose trois façons distinctes d’itĂ©rer sur une collection.
Ce n’est pas redondant, chaque approche rĂ©pond Ă un besoin prĂ©cis. Les confondre, c’est un peu comme utiliser un tournevis pour planter un clou : techniquement possible, mais pas optimal.
Le mot-clĂ© foreach charge l’intĂ©gralitĂ© de la collection en mĂ©moire avant de commencer l’itĂ©ration. Sa syntaxe de base est claire :
foreach ($item in $collection) {
# bloc de code
}Rapide pour des collections de taille modĂ©rĂ©e, il devient gourmand sur de trĂšs gros volumes. PowerShell crĂ©e automatiquement la variable $item et la met Ă jour Ă chaque itĂ©ration, aucune dĂ©claration prĂ©alable n’est nĂ©cessaire.

Le cmdlet ForEach-Object (alias %) fonctionne diffĂ©remment : il traite chaque objet au fil du pipeline, sans charger toute la collection en mĂ©moire d’un coup. IdĂ©al pour les gros flux de donnĂ©es. L’objet courant est abordable via la variable automatique $_. En revanche, la surcharge par cmdlet le rend un peu plus lent sur de petites collections.
Introduite avec PowerShell 4, la mĂ©thode .ForEach() s’applique directement sur une collection dĂ©jĂ en mĂ©moire. Sa syntaxe est concise :
$collection.ForEach({ $_.Name })Elle surpasse ForEach-Object en termes de performances sur les collections déjà chargées.
| Approche | Chargement mémoire | Performance | Usage typique |
|---|---|---|---|
đč foreach | Collection entiĂšre | Express (petites/moyennes collections) | Scripts locaux, tableaux connus |
đž ForEach-Object | Objet par objet | Plus lent, Ă©conome en mĂ©moire | Pipeline, gros flux |
đą .ForEach() | Collection entiĂšre | TrĂšs rapide | Collections dĂ©jĂ en mĂ©moire (PS4+) |
Mon conseil : si vous traitez des fichiers journaux ou des flux réseau (si vous vous demandez comment fonctionne un réseau informatique, ça mérite un détour), préférez ForEach-Object. Pour un tableau de 200 utilisateurs à créer dans Active Directory, le mot-clé foreach sera plus lisible et plus express.
đ ïž Cas d’usage concrets : Ce qu’on fait vraiment avec foreach
Parlons utile. Voici les situations oĂč la boucle foreach PowerShell devient indispensable au quotidien.
Filtrer des fichiers par taille ou par date est un classique absolu. Pour supprimer les fichiers non modifiés depuis plus de 7 jours dans un dossier temporaire :
foreach ($fichier in Get-ChildItem "C :\Temp") {
if ($fichier.LastWriteTime -lt (Get-Date).AddDays(-7)) {
Remove-Item $fichier.FullName
}
}Pour ne traiter que les fichiers dĂ©passant 100 Ko, il suffit d’ajouter $fichier.Length -gt 102400 dans la condition. Les propriĂ©tĂ©s accessibles via notation pointĂ©e ($fichier.Length, $fichier.CreationTime, $fichier.Name) rendent le code extrĂȘmement lisible.
Autre cas trĂšs frĂ©quent : crĂ©er des utilisateurs en masse dans Active Directory depuis un fichier CSV. J’ai dĂ©jĂ automatisĂ© l’intĂ©gration de 300 comptes en moins de 5 minutes avec une boucle de ce type. Ajoutez un bloc Try-Catch autour des opĂ©rations sensibles pour que l’exĂ©cution continue mĂȘme si un compte pose problĂšme.
- đïž Copier des fichiers en ajoutant un suffixe
_backup - đ Analyser des fichiers journaux avec le cmdlet
Get-WinEvent - âïž RedĂ©marrer ou vĂ©rifier l’Ă©tat de services Windows sur plusieurs machines
- đ Manipuler des clĂ©s de registre en lot
Un dĂ©tail important : utilisez Write-Output plutĂŽt que Write-Host, qui bloque la redirection de flux. C’est le genre d’habitude qui distingue un script qu’on peut chaĂźner d’un script qu’on jette aprĂšs usage.
⥠Parallélisation avec ForEach-Object : La vitesse avec méthode
Disponible depuis PowerShell 7, le paramĂštre -Parallel de ForEach-Object change la donne pour les traitements lourds. Par dĂ©faut, 5 blocs de script s’exĂ©cutent simultanĂ©ment (paramĂštre ThrottleLimit), une valeur ajustable selon les ressources disponibles.
Cas concret : rĂ©cupĂ©rer 50 000 entrĂ©es de journal depuis 5 journaux systĂšme diffĂ©rents en parallĂšle rĂ©duit drastiquement le temps d’exĂ©cution. La parallĂ©lisation brille spĂ©cialement sur les opĂ©rations qui attendent une rĂ©ponse : appels distants, temporisations, requĂȘtes rĂ©seau.
Attention par contre : pour des scriptblocks trivials, la crĂ©ation d’espaces d’exĂ©cution (runspaces) coĂ»te plus cher que ce qu’elle rapporte. Utilisez le cmdlet Measure-Command pour mesurer objectivement le gain avant de parallĂ©liser Ă tout prix. Depuis PowerShell 7.1, les runspaces sont rĂ©utilisĂ©s par dĂ©faut, ce qui amĂ©liore les performances. Depuis PowerShell 7.2, la modification de propriĂ©tĂ©s dans des blocs parallĂšles imbriquĂ©s est possible.
Pour passer des variables dans un bloc parallÚle, le modificateur $using : est obligatoire. Pour collecter les résultats de façon sûre, la classe System.Collections.Concurrent.ConcurrentDictionary est votre alliée : elle gÚre les accÚs concurrents sans conflits.

Si vous aimez automatiser et scripter, vous apprĂ©cierez sĂ»rement aussi de savoir comment dĂ©velopper une extension Chrome pour pousser l’automatisation cĂŽtĂ© navigateur. Et lĂ , ma femme ne me demande plus pourquoi je passe mes soirĂ©es devant un terminal… enfin, presque.
