PowerShell each : MaĂźtrisez les boucles

Un développeur observe un terminal flouté accompagné de symboles de boucle abstraits.

Idées principalesDétails et application
🔄 Trois mĂ©thodes d’itĂ©rationComparer foreach, ForEach-Object et .ForEach() pour choisir l’optimale.
⚡ Foreach charge la collectionRapide pour petites collections, gourmand en mĂ©moire pour gros volumes de donnĂ©es.
🌊 ForEach-Object traite au pipelineTraiter objet par objet sans charger l’intĂ©gralitĂ© en mĂ©moire, idĂ©al gros flux.
🚀 .ForEach() surpasse les autresMĂ©thode PowerShell 4+ trĂšs performante pour collections dĂ©jĂ  chargĂ©es.
📁 Filtrer fichiers par dateSupprimer fichiers non modifiĂ©s depuis 7 jours avec conditions simples.
đŸ‘„ CrĂ©er utilisateurs en masseAutomatiser Active Directory avec boucles et blocs Try-Catch robustes.
⚙ ParallĂ©lisation disponibleParamĂštre -Parallel depuis PowerShell 7, jusqu’Ă  5 exĂ©cutions simultanĂ©es.
🔐 SĂ©curiser les donnĂ©es parallĂšlesUtiliser 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.

Plusieurs écrans de développement affichent des interfaces techniques abstraites.

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.

ApprocheChargement mémoirePerformanceUsage typique
đŸ”č foreachCollection entiĂšreExpress (petites/moyennes collections)Scripts locaux, tableaux connus
🔾 ForEach-ObjectObjet par objetPlus lent, Ă©conome en mĂ©moirePipeline, gros flux
🟱 .ForEach()Collection entiĂšreTrĂšs rapideCollections 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.

Nous serions ravis de connaĂźtre votre avis

      Laisser un commentaire

      Croc Informatique - Partageons nos Connaissances
      Logo