Les scripts sous PowerShell
Ces manipulations visent à vous familiariser avec les scripts PowerShell. Une fois ces manipulations effectuées, vous pouvez vous pratiquer avec les exercices pour la semaine 3.
Création d'un profil (facultatif)
Un profil PowerShell est un script qui s'exécute automatiquement à chaque démarrage de PowerShell. Il permet de personnaliser votre environnement PowerShell en définissant des variables, des alias, des fonctions, etc. C'est l'équivalent du fichier .bashrc sous Linux.
Tout d'abord, effectuez cette commande:
$Profile | Select-Object *
À titre de rappel, $Profile est une variable automatique qui contient le chemin du fichier de profil actuel. Le symbole | est un opérateur de pipeline qui permet de passer la sortie d'une commande comme entrée à une autre commande. La commande Select-Object * affiche toutes les propriétés de l'objet $Profile, y compris les chemins des différents profils disponibles.
Vous devriez voir plusieurs chemins de fichiers. Le chemin que nous allons utiliser est celui qui correspond à CurrentUserCurrentHost, soit l'utilisateur actuel et l'hôte actuel.
Maintenant, pour modifier le profil, vous pouvez utiliser la commande suivante:
New-Item -ItemType File -Value 'Write-Host "Bonjour <votre nom>!"' -Path $Profile.CurrentUserCurrentHost -Force
Attention, cette commande écrasera le contenu actuel de votre profil s'il existe déjà. Si vous avez déjà personnalisé votre profil, vous pouvez ouvrir le fichier avec un éditeur de texte et ajouter la ligne Write-Host "Bonjour <votre nom>!" à la fin du fichier.
N'oubliez pas de remplacer <votre nom> par votre prénom.
Finalement, pour que les modifications prennent effet, vous devez redémarrer PowerShell ou exécuter la commande suivante:
. $Profile.CurrentUserCurrentHost
Maintenant, chaque fois que vous ouvrirez PowerShell, il affichera "Bonjour
Création et exécution d'un script
Un script PowerShell est un fichier texte contenant une série de commandes PowerShell. Pour créer un script, vous pouvez utiliser n'importe quel éditeur de texte, mais il est recommandé d'utiliser PowerShell ISE ou Visual Studio Code pour bénéficier de la coloration syntaxique et de l'auto-complétion.
Créez un fichier texte avec l'extension .ps1, par exemple mon_script.ps1, et ajoutez-y les lignes suivantes:
Write-Host "Bonjour, monde!"
Pour exécuter le script, ouvrez PowerShell, naviguez jusqu'au répertoire où se trouve le script, puis tapez:
.\mon_script.ps1
Si votre script ne s'exécute pas, c'est probablement à cause de la politique d'exécution des scripts. Par défaut, PowerShell bloque l'exécution de scripts pour des raisons de sécurité. Vous pouvez vérifier la politique d'exécution actuelle avec la commande suivante:
Get-ExecutionPolicy
Si vous obtenez Restricted, vous devrez modifier la politique d'exécution pour permettre l'exécution de scripts. Pour cela, utilisez la commande Set-ExecutionPolicy. Par exemple, pour autoriser l'exécution de scripts téléchargés signés (mais locaux non signés), vous pouvez utiliser:
Set-ExecutionPolicy RemoteSigned
Les variables
Modifiez maintenant votre script mon_script.ps1 pour inclure une variable:
$nom = "Eva"
$message = "Bonjour! La valeur de la variable `$nom est $nom!"
Write-Host $message
Ici, nous avons créé une variable $nom qui stocke le nom "Eva". Nous avons également créé une variable $message qui utilise l'interpolation de variables pour inclure la valeur de $nom dans une chaîne de caractères. Notez que pour afficher le symbole $ dans une chaîne entre guillemets doubles, nous devons l'échapper avec un backtick (`). Cela permet d'afficher littéralement $nom dans le message.
Les paramètres
Pour rendre votre script plus flexible, vous pouvez ajouter des paramètres. Modifiez votre script mon_script.ps1 pour inclure un paramètre:
param (
[string]$nom = "monde"
)
$message = "Bonjour! La valeur de la variable `$nom est $nom!"
Write-Host $message
Vous pouvez maintenant exécuter votre script en passant un argument pour le paramètre $nom:
.\mon_script.ps1 -nom "Eva"
Cela affichera "Bonjour! La valeur de la variable $nom est Eva!". Si vous n'indiquez pas de valeur pour le paramètre, il utilisera la valeur par défaut "monde".
La substitution de commandes
La substitution de commandes permet d'exécuter une commande et d'utiliser sa sortie comme partie d'une autre commande. En PowerShell, cela se fait en utilisant des parenthèses (). Par exemple, modifiez votre script mon_script.ps1 pour inclure la date actuelle:
param (
[string]$nom = "monde"
)
$date = (Get-Date -Format "dd/MM/yyyy")
$message = "Bonjour! La valeur de la variable `$nom est $nom! Aujourd'hui, nous sommes le $date."
Write-Host $message
Les tableaux
Ajoutons maintenant un tableau à notre script. Modifiez mon_script.ps1 pour inclure un tableau de noms:
param (
[string[]]$noms = @("Alice", "Bob", "Charlie")
)
$date = (Get-Date -Format "dd/MM/yyyy")
foreach ($nom in $noms) {
$message = "Bonjour! La valeur de la variable `$nom est $nom! Aujourd'hui, nous sommes le $date."
Write-Host $message
}
Nous verrons plus en détail les boucles dans la section suivante, mais pour l'instant, sachez que la boucle foreach itère sur chaque élément du tableau $noms et exécute le bloc de code pour chaque nom.
La commande @("Alice", "Bob", "Charlie") crée un tableau contenant trois chaînes de caractères. Le paramètre $noms est défini comme un tableau de chaînes de caractères avec une valeur par défaut. Nous utilisons la syntaexe [string[]] pour indiquer que le paramètre est un tableau de chaînes de caractères.
Il est possible de passer plusieurs noms en arguments lors de l'exécution du script:
.\mon_script.ps1 -noms "Eva", "Liam", "Noah"
Il aurait également été possible de déclarer le tableau directement dans le script sans passer par un paramètre:
$noms = @("Alice", "Bob", "Charlie")
$date = (Get-Date -Format "dd/MM/yyyy")
foreach ($nom in $noms) {
$message = "Bonjour! La valeur de la variable `$nom est $nom! Aujourd
'hui, nous sommes le $date."
Write-Host $message
}
Les tables de hachage
Nous allons inclure une table de hachage dans notre script. Modifiez mon_script.ps1 pour inclure une table de hachage de noms et âges:
$personne = @{
Nom = "Alice"
Age = 30
Ville = "Montreal"
}
$date = (Get-Date -Format "dd/MM/yyyy")
$message = "Bonjour! Le nom est $($personne.Nom), l'âge est $($personne.Age) et la ville est $($personne.Ville). Aujourd'hui, nous sommes le $date."
Write-Host $message
Les structures conditionnelles (if/elseif/else)
Pour pratiquer les structures conditionnelles, nous allons créer un script qui effectue une sauvegarde (backup) de fichiers. Créez un nouveau fichier sauvegarde.ps1 et ajoutez-y le code suivant:
param (
[string]$source,
[string]$destination
)
$date = Get-Date -Format "yyyyMMdd_HHmmss"
$backupPath = Join-Path -Path $destination -ChildPath "Backup_$date"
Compress-Archive -Path $source -DestinationPath "$backupPath.zip"
Write-Host "Sauvegarde de $source vers $backupPath.zip effectuée avec succès."
Ce script prend deux paramètres: le chemin source des fichiers à sauvegarder et le chemin de destination où la sauvegarde sera stockée. Il crée un fichier ZIP avec un horodatage pour éviter d'écraser les sauvegardes précédentes.
Vous pouvez exécuter le script comme suit:
.\sauvegarde.ps1 -source "C:\Chemin\Vers\Source" -destination "C:\Chemin\Vers\Destination"
Maintenant, pour rajouter des boucles de contrôle, modifiez le script pour vérifier si les chemins source et destination existent avant de procéder à la sauvegarde:
param (
[string]$source,
[string]$destination
)
if (-Not (Test-Path -Path $source)) {
Write-Host "Le chemin source $source n'existe pas."
exit
} elseif (-Not (Test-Path -Path $destination)) {
Write-Host "Le chemin de destination $destination n'existe pas."
exit
} else {
$date = Get-Date -Format "yyyyMMdd_HHmmss"
$backupPath = Join-Path -Path $destination -ChildPath "Backup_$date"
Compress-Archive -Path $source -DestinationPath "$backupPath.zip"
Write-Host "Sauvegarde de $source vers $backupPath.zip effectuée avec succès."
}
Ici, nous utilisons Test-Path pour vérifier l'existence des chemins. Cette fonctionne retoune $true si le chemin existe et $false sinon. Le premier test vérifie si le chemin source n'existe pas, et si c'est le cas, affiche un message d'erreur et quitte le script. Le second test fait de même pour le chemin de destination. Si les deux chemins existent, la sauvegarde est effectuée.
Boucles for, foreach, ForEach-Object et while
Pour pratiquer les boucles, nous allons créer un script qui liste tous les fichiers dans un répertoire donné et affiche leurs noms. Créez un nouveau fichier lister_fichiers.ps1 et ajoutez-y le code suivant:
param (
[string]$repertoire
)
if (-Not (Test-Path -Path $repertoire)) {
Write-Host "Le répertoire $repertoire n'existe pas."
exit
} else {
$fichiers = Get-ChildItem -Path $repertoire
foreach ($fichier in $fichiers) {
Write-Host $fichier.Name
}
}
Ce script prend un paramètre: le chemin du répertoire à lister. Il vérifie d'abord si le répertoire existe, puis utilise Get-ChildItem pour obtenir tous les fichiers dans le répertoire. La boucle foreach itère sur chaque fichier et affiche son nom.
Boucle for
Pour pratiquer la boucle for, nous allons créer un script qui crée une série de dossiers numérotés. Créez un nouveau fichier creer_dossiers.ps1 et ajoutez-y le code suivant:
param (
[string]$basePath,
[int]$nombreDossiers
)
if (-Not (Test-Path -Path $basePath)) {
Write-Host "Le chemin de base $basePath n'existe pas."
exit
} else {
for ($i = 1; $i -le $nombreDossiers; $i++) {
$dossierPath = Join-Path -Path $basePath -ChildPath "Dossier_$i"
New-Item -ItemType Directory -Path $dossierPath -Force
Write-Host "Dossier créé: $dossierPath"
}
}
Ce script prend deux paramètres: le chemin de base où les dossiers seront créés et le nombre de dossiers à créer. Il vérifie d'abord si le chemin de base existe, puis utilise une boucle for pour créer les dossiers numérotés. La boucle for prend 3 parties: l'initialisation ($i = 1), la condition ($i -le $nombreDossiers), et l'incrémentation ($i++). Pour chaque itération, il crée un nouveau dossier avec un nom basé sur le numéro de l'itération grâce à New-Item.
Boucle foreach
Pour pratiquer la boucle foreach, nous allons créer un script qui lit une liste de noms à partir d'un fichier texte et affiche un message personnalisé pour chaque nom. Créez un nouveau fichier saluer_noms.ps1 et ajoutez-y le code suivant:
param (
[string]$fichierNoms
)
if (-Not (Test-Path -Path $fichierNoms)) {
Write-Host "Le fichier $fichierNoms n'existe pas."
exit
} else {
$noms = Get-Content $fichierNoms
foreach ($nom in $noms){
Write-Host "Bonjour $nom, bienvenue!"
}
}
Ce script prend un paramètre: le chemin du fichier texte contenant les noms. Il vérifie d'abord si le fichier existe, puis utilise Get-Content pour lire chaque ligne du fichier. La boucle Foreach itère sur chaque ligne (chaque nom) et affiche un message de salutation personnalisé.
Pour l'exécuter, créez un fichier texte (par exemple noms.txt) avec une liste de noms, un par ligne, puis exécutez le script comme suit:
.\saluer_noms.ps1 -fichierNoms "C:\Chemin\Vers\noms.txt"
Boucle ForEach-Object
Nous allons modifier l'exemple précédent pour utiliser ForEach-Object. Voici comment modifier le script :
param (
[string]$fichierNoms
)
if (-Not (Test-Path -Path $fichierNoms)) {
Write-Host "Le fichier $fichierNoms n'existe pas."
exit
} else {
Get-Content $fichierNoms | ForEach-Object {
Write-Host "Bonjour $_, bienvenue!"
}
}
Ici, chaque ligne du fichier est transmise au bloc ForEach-Object via le pipeline, et la variable automatique $_ contient la valeur courante (le nom).
Boucle while
Pour pratiquer la boucle while, nous allons créer un script qui demande à l'utilisateur de saisir des nombres jusqu'à ce qu'il saisisse "exit". Le script additionnera tous les nombres fournis par l'utilisateur.
Créez un nouveau fichier somme_nombres.ps1 et ajoutez-y le code suivant:
$nombre = ""
$somme = 0
while ($nombre -ne "exit") {
$nombre = Read-Host "Veuillez saisir un nombre (ou 'exit' pour quitter)"
if ($nombre -ne "exit") {
$somme += [int]$nombre
}
}
Write-Host "La somme des nombres saisis est: $somme"
Ce script utilise une boucle while pour continuer à demander à l'utilisateur de saisir un nombre. La condition de la boucle est que la variable $nombre ne doit pas être égale à "exit". Si l'utilisateur saisit un nombre, le script l'ajoute à la somme. Si l'utilisateur saisit "exit", la boucle se termine.
Les tableaux et les tables de hachage
Pour pratiquer de nouveau les tableaux et les tables de hachage, nous allons créer un script qui stocke les noms et âges des utilisateurs dans un tableau et une table de hachage, puis affiche ces informations.
Créez un nouveau fichier stockage_informations.ps1 et ajoutez-y le code suivant:
# Tableau pour stocker les informations
$informations = @()
# Table de hachage pour stocker les informations
$tableHachage = @{}
# Boucle pour saisir les informations
do {
$nom = Read-Host "Veuillez saisir un nom (ou 'exit' pour quitter)"
if ($nom -ne "exit") {
$age = Read-Host "Veuillez saisir l'âge de $nom"
$informations += [PSCustomObject]@{ Nom = $nom; Age = $age }
$tableHachage[$nom] = $age
}
} while ($nom -ne "exit")
# Affichage des informations stockées dans le tableau
Write-Host "Informations stockées dans le tableau:"
$informations | ForEach-Object {
Write-Host "Nom: $($_.Nom), Age: $($_.Age)"
}
# Affichage des informations stockées dans la table de hachage
Write-Host "Informations stockées dans la table de hachage:"
$tableHachage.GetEnumerator() | ForEach-Object {
Write-Host "Nom: $($_.Key), Age: $($_.Value)"
}
Ce script utilise un tableau pour stocker des objets personnalisés contenant des noms et des âges, et une table de hachage pour stocker les âges associés aux noms. Les informations sont saisies dans une boucle do...while et affichées à la fin.