Quelle est la différence entre un script que vous exécuteriez 5 fois pour 5 actions identiques (par exemple un script qui demande d’entrer un nombre et de vérifier si c’est bien le nombre secret à trouver), et un script qui vous demanderait d’entrer un nombre tant que vous n’avez pas trouvé le nombre secret ?
Dans les deux cas, nous sommes sur un script interactif. Dans les deux cas aussi, l’objectif est de trouver le nombre secret.
Mais dans un des cas, vous allez devoir systématiquement exécuter de nouveau votre script pour retenter votre chance, et dans l’autre non.
Autre exemple : imaginez que vous souhaitiez exécuter exactement 3 fois une instruction dans votre script.
Affirmer son amour pour le comique de répétition ?
Par exemple, oui ! Jusqu’à présent, votre seule possibilité était d’écrire 3 Write-Host
“J’aime le comique de répétition” à la suite :
Write-Host “J’aime le comique de répétition”
Write-Host “J’aime le comique de répétition”
Write-Host “J’aime le comique de répétition”
Ça fonctionne oui, mais c’est dupliquer du code. Et nous n’aimons pas dupliquer du code.
Surtout que si pour une raison particulière, vous décidez que pour déclarer votre flamme à un type d’humour particulier, vous devez non plus l’appeler 3 fois, mais 4, vous devrez obligatoirement passer par l’édition du script avant, pour ajouter une ligne.
Vous allez apprendre dans ce chapitre à créer des boucles. Ces boucles ont pour objectif de vous permettre d’effectuer des actions à plusieurs reprises sans avoir à dupliquer votre code.
La boucle while{}
La première boucle dont nous allons parler est celle qu’on peut traduire en français par “Faire tant que”.
Cette boucle est utilisée dans le cas où, comme le nom l’indique, une action doit être effectuée tant que la condition de test est vraie.
Mais les conditions, ce n’est pas ce qu’on a vu juste avant ?
Eh bien si ! Et les boucles fonctionnent de pair avec la logique employée pour les structures conditionnelles.
D’ailleurs, vous pouvez voir sur l’organigramme suivant comment pourrait être représentée une boucle “Tant que” :
Reprenons notre exemple, et essayons de voir comment nous allons utiliser cette boucle while{}.
Nous devions demander à l’utilisateur d’entrer un nombre, tant que celui-ci n’était pas le nombre secret.
Voici comment nous pouvons illustrer ceci en PowerShell :
$nombreSecret = 42
while ((Read-Host "Entrez un nombre") -ne $nombreSecret)
{
Write-Host “Vous n’avez pas trouvé le nombre secret. Recommencez ! “
}
Write-Host "Le nombre secret a été dévoilé"
La boucle for{}
La boucle for pourrait être traduite en français comme “Faire N fois”.
C’est la boucle qu’on va utiliser principalement lorsque nous connaissons le nombre d’itérations.
Là encore, nous pouvons reprendre notre exemple "J'aime le comique de répétition !".
for ($iterateur=0; $iterateur -lt 3; $iterateur++)
{
Write-Host "J'aime le comique de répétition !"
}
La boucle for en PowerShell utilise 3 informations lors de la déclaration :
un itérateur et sa valeur de départ. Dans notre cas, il s’agit de la variable $iterateur = 0 ;
le test pour vérifier la sortie de boucle. Ici, il s’agit de vérifier que la valeur de l’itérateur est inférieur à 3 avec le test $iterateur -lt 3 ;
la valeur de l’incrémentation. Nous faisons le choix d’incrémenter de 1 en 1 notre variable $iterateur. Mais nous pourrions aussi bien augmenter de 5 en 5 ou de 10 en 10.
Mais alors c’est quoi l'intérêt d’avoir une boucle for ? Nous aurions très bien pu faire pareil avec une boucle while, non ?
Eh bien dans ce cas-là… totalement ! D’ailleurs, il n’y a aucune obligation d’utiliser l’une ou l’autre des boucles.
Le fait d’utiliser une boucle for quand nous connaissons le nombre de boucles à effectuer n’est qu’une habitude, et non une obligation.
La boucle foreach{}
La dernière boucle que nous allons voir dans ce chapitre est la boucle foreach, que nous pouvons traduire en “Pour chaque”.
Cette boucle s’utilise uniquement avec ce qu’on va appeler une collection. Une collection peut être aussi bien un tableau que des lignes d’un fichier texte, le résultat d’une cmdlet ou d’un CSV (Common Separated Value), par exemple.
La syntaxe est la suivante :
foreach ($<item> in $<collection>;)
{
#instructions
}
Prenons un exemple avec un tableau composé de prénoms :
$prenoms = “Erwann”, “Yann”, “Gwendall”
Nous allons pouvoir boucler sur la liste de prénoms, en affectant une variable à chaque boucle comprenant l’item en cours de notre tableau.
Ce qui donne le code suivant :
$prenoms = “Erwann”, “Yann”, “Gwendall”
foreach ($prenom in $prenoms)
{
Write-Host "Bonjour $prenom"
}
Couplé avec un fichier CSV, vous obtenez une très bonne base pour automatiser des actions en masse.
Enfin, la boucle foreach peut s’utiliser avec une autre syntaxe. En effet, nous pouvons passer la collection directement en pipeline et utiliser Foreach-Object à la suite.
$prenoms = “Erwann”, “Yann”, “Gwendall”
$prenoms |ForEach-Object {"Bonjour "+$_}
Les deux syntaxes se valent. À vous d’utiliser celle avec laquelle vous êtes le plus à l’aise.
Automatisez des actions en masse
Comme je vous le disais au début du chapitre, vous avez précédemment appris à développer des scripts comprenant principalement des suites d’actions.
Maintenant que vous avez connaissance des boucles, vous allez enfin pouvoir commencer à réfléchir pour automatiser des actions en masse.
D’accord, mais qu’est-ce que vous entendez par actions en masse ?
Il s’agit d’un script qui est en capacité de traiter beaucoup de données. Et surtout de le faire de manière autonome.
Dans une certaine mesure, il est un peu l’inverse du script interactif, qui lui, va se baser sur les informations récupérées directement par l’utilisateur.
Imaginez, pour des raisons techniques, un script qui récupère une liste de fichiers externes, en CSV par exemple, et qui doit vérifier si le fichier existe ou pas.
Ce cas de figure vous montre le principe de l’automatisation d’une action en masse.
Notre script fonctionne autour d’une boucle foreach, élément essentiel d’un parcours de CSV, et de la cmdlet Import-Csv
.
En langage plus humain, ça correspondrait à ceci :
ouvrez le fichier CSV et stockez-le dans la variable $listeDesFichiers ;
pour chaque ligne de ma variable $listeDesFichers, créez la variable $fichier, qui correspond à la liste en cours :
si le résultat de la cmdlet Test-Path est vrai, écrivez dans la console le fichier nommé en prenant le champ fichier de la variable $fichier,
sinon, écrivez un message disant qu’il n’est pas existant.
À vous de jouer !
Pour cet exercice, vous allez télécharger le fichier CSV suivant :
prenom,nom
Mac,Giver
Sarah,Connor
Tom,Baker
David,Tennant
Matt,Smith
Peter,Capaldi
Vous allez ensuite créer un script qui va ajouter un répertoire par utilisateur dans c:\sauvegardes.
Ces répertoires devront être sous la forme : Première lettre du prenom.nom, le tout en minuscules.
Par exemple pour Mac Giver, le dossier sera “c:\sauvegarde\m.giver”.
Mais avant de créer le répertoire, vous devrez tester si celui-ci existe ou non !
Allez, pour vous aider, voici une ébauche d’algorithme que vous pourriez mettre en place pour arriver au bon nom de répertoire :
Pour chaque ligne du CSV :
créer une variable composée de la première lettre du prénom avec un Substring, concaténer avec un “.” et ajouter le nom complet ;
mettre cette variable en minuscules avec toLower() ;
tester si le dossier avec ce nom existe :
s’il n’existe pas : le créer et mettre un message de confirmation,
s’il existe : mettre un message et passer au suivant.
*
*
*
*
*
*
Voilà la correction. N’hésitez pas à aller comparer votre travail. Et si tout n’est pas exactement pareil, ce n’est pas grave, si votre code fonctionne, et que la logique est là, c’est très bien.
<#
Description : Script permettant de créer en masse des dossiers utilisateurs
Usage : createDir.ps1
Auteur : Stiven G.
Version : 0.3
Révisions :
-0.2 (27/09/2022): Ajout de la fonction Add-ToLogFile(String texteAAjouter)
Ajout des blocs try{}/catch{}
-0.1 (27/06/2022) : Version Initiale
#>
function Add-ToLogFile($texteAAjouter) {
$dateAction = Get-Date -Format "yyyyMMdd HH:mm:ss"
Add-Content -Value $dateAction" -- "$texteAAjouter -Path "log.txt"
}
$destination = "c:\users\stiven\"
$UserList = Import-Csv -Path "C:\Users\stiven\Documents\users_to_create.csv"
#boucle sur les lignes du CSV
foreach($ligne in $UserList) {
$dirName = ($ligne.prenom.Substring(0,1)+"."+$ligne.nom).toLower()
try{
#Tentative de création du dossier
New-Item $destination$dirName `
-ItemType Directory `
-ErrorAction Stop
Add-ToLogFile("Le dossier de l'utilisateur $dirName a été créé")
}
Catch {
Add-ToLogFile("ERREUR à la creation du dossier : "+$_.exception.message)
}
}
En résumé
Un test ou une condition permet de vérifier si quelque chose est vrai ou faux.
Il existe au moins deux types de structures conditionnelles : les bloc if…then…else et les blocs Switch.
Les tests vont toujours de pair avec les booléens true ou false.
Il existe 3 type de boucles sous PowerShell : while, for et foreach.
Fonctionner avec des boucles permet d’augmenter le niveau d’automatisation en permettant des traitements sur un grand nombre de données.
Les fichiers CSV (Common Separated Values) sont les candidats parfaits pour de l’import en masse. Mais ils ne sont pas les seuls.
Vous avez désormais toutes les clés en main pour pouvoir développer des scripts fonctionnels qui réalisent des actions automatisées, en masse ou de manière interactive. Il vous reste maintenant à apprendre à gérer les erreurs d’exécution.