PowerShell each : Maîtrisez les boucles
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.
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 _backupAnalyser des fichiers journaux avec le cmdlet Get-WinEventRedé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.
L’article PowerShell Each Loop : Boucles, ForEach-Object et Astuces ⚡ est apparu en premier sur Croc Informatique - Partageons nos Connaissances.