Get-Content : comment lire le contenu d’un fichier en PowerShell ?
Sommaire
I. Présentation
Le cmdlet Get-Content fait partie des commandes incontournables lorsque l'on s'intéresse au scripting PowerShell. Il va permettre de lire le contenu d'un fichier en PowerShell, ce qui est une action très courante. En plus de lire les données, on va pouvoir importer les données dans une variable pour les exploiter dans le script PowerShell. On peut utiliser Get-Content pour récupérer le contenu d'un fichier de log, par exemple.
Nous verrons que Get-Content est un cmdlet puissant qui est capable de faire plus que simplement récupérer le contenu d'un fichier intégralement, d'où l'intérêt de lui dédier un article complet. Ce cmdlet fonctionne sous Windows Powershell 5.1 et PowerShell, notamment dans la dernière version à ce jour : PowerShell 7.1.1.
? Tutoriel disponible au format vidéo :
II. Lire simplement le contenu d'un fichier
Pour commencer, on va simplement lire le contenu d'un fichier texte qui contiendra une liste de valeurs. Pour suivre ce tutoriel, je vous invite à créer un fichier nommé "Pays.txt" et stocké dans "C:\TEMP". Ce fichier doit avoir le contenu suivant :
France Costa Rica Belgique Suisse Espagne Colombie Canada Brésil Islande Nicaragua
Pour lire et afficher dans la console le contenu de ce fichier, la commande est super simple puisqu'il suffit de préciser le nom du fichier (ou le chemin complet s'il n'est pas dans le répertoire courant) :
Get-Content "C:\TEMP\Pays.txt"
Le paramètre -Path sera utilisé de manière implicite pour cette valeur. Si l'on écrit la commande ci-dessous, cela revient au même.
Get-Content -Path "C:\TEMP\Pays.txt"
Afficher le contenu dans la console ne donne pas grand-chose. C'est plus intéressant quand on va stocker le contenu du fichier dans une variable dans le but de l'exploiter. Il suffit de créer une variable, par exemple $Pays, et de lui attribuer le contenu du fichier comme valeur :
$Pays = Get-Content "C:\TEMP\Pays.txt"
Par curiosité, on peut regarder le type de la variable $Pays après lui avoir attribué une valeur :
$Pays.GetType()
On peut voir que l'on obtient deux informations pertinentes : "Object[]" et "System.Array". Nous avons affaire à un objet sous la forme d'un tableau de valeurs ; c'est intéressant ! ?
Pour compter le nombre d'éléments dans ce fichier texte, on peut le faire de deux façons différentes :
$Pays.Count ($Pays | Measure-Object).Count
Nous avons 10 éléments, puisqu'il s'agit d'un tableau la première valeur correspond à l'index 0 et la dernière à l'index 9 (puisque l'on a seulement 10 éléments). Ainsi, la valeur à l'index 0 sera "France" et celle à l'index 9 sera Nicaragua.
Si l'on veut consulter la valeur située en index 0, c'est-à-dire la première valeur, c'est tout simple :
$Pays[0]
Ou si vous préférez, cela revient à faire :
(Get-Content "C:\TEMP\Pays.txt")[0]
Dans le même esprit, pour récupérer la dernière valeur sans connaître le numéro d'index exact, il y a une astuce ! Il suffit d'utiliser "-1" comme numéro pour l'index :
(Get-Content "C:\TEMP\Pays.txt")[-1]
Au lieu de récupérer le contenu du fichier sous la forme d'un tableau, on peut le récupérer comme une seule chaîne de caractères. Il suffit d'ajouter le paramètre -Raw à la commande :
Get-Content -Path "C:\TEMP\Pays.txt" -Raw
Passons à la suite avec quelques exemples pratiques.
III. Le tail de Linux à la mode PowerShell
Sous Linux, il est très fréquent d'utiliser la commande tail pour afficher les dernières lignes d'un fichier. Bien souvent, je l'utilise pour consulter un fichier de log, d'autant plus que la sortie est dynamique : si des lignes sont ajoutées au fichier, elles s'afficheront dans la console au fur et à mesure.
C'est très pratique et c'est possible de faire la même chose en PowerShell, à l'aide de Get-Content et d'une option qui se nomme... -Tail et d'une deuxième option -Wait ! ?
Sans l'option -Wait, on peut récupérer les X dernières lignes d'un fichier en utilisant -Tail tout seul. Par exemple, pour récupérer les 5 dernières lignes de notre fichier Pays.txt :
Get-Content "C:\TEMP\Pays.txt" -Tail 5
Maintenant, si l'on veut afficher les 5 dernières lignes et attendre pour récupérer les futures lignes ajoutées au fichier, on va utiliser cette syntaxe :
Get-Content "C:\TEMP\Pays.txt" -Tail 5 -Wait
Pour faire le test, exécutez la commande ci-dessus puis modifiez le fichier "Pays.txt" pour ajouter une ligne : vous verrez qu'elle s'affiche quasiment en temps réel dans la console PowerShell où la commande tourne ?.
En fait, grâce à la commande -Wait, Get-Content maintient le fichier ouvert et vérifie chaque seconde s'il y a du nouveau contenu à afficher. Pour terminer l'exécution de la commande, c'est tout simple, il suffit d'effectuer un "CTRL + C".
Il est à noter que vous pouvez utiliser l'option -Wait seule : dans ce cas, le fichier va s'afficher en intégralité dans la console et ensuite il va rester en attente.
Get-Content "C:\TEMP\Pays.txt" -Wait
IV. Récupérer les X premières lignes d'un fichier
Dans le même esprit, on peut récupérer les premières lignes d'un fichier. Dans ce cas, on ne va pas utiliser -Tail mais plutôt -TotalCount à la place. Là encore, il faut spécifier le nombre de lignes à afficher.
Get-Content "C:\TEMP\Pays.txt" -TotalCount 5
Par contre, et c'est logique, l'option -Wait n'a pas d'utilité avec l'option -TotalCount.
V. NTFS : consulter un stream secret dans un fichier
Le système de fichiers NTFS a la particularité d'avoir différents "stream" dans lequel stocker les données. Lorsque l'on écrit des données dans un fichier, elles sont stockées dans le flux $DATA. Ainsi, lorsque l'on consulte le fichier, on va lire le contenu de ce flux de données.
D'ailleurs, on peut voir que notre fichier "Pays.txt" dispose bien de ce stream grâce à la commande Get-Item :
Get-Item "C:\TEMP\Pays.txt" -Stream *
On remarque également que la console retourne seulement ce flux de données.
Là où c'est cool, c'est que l'on peut créer son propre stream pour cacher des données à l'intérieur ! ?
Il suffit d'ajouter des données à notre fichier "Pays.txt" en spécifiant le stream dans lequel envoyer les données. Par exemple, nous allons créer le stream "Creds" avec la valeur "MotDePasse".
Add-Content -Path "C:\TEMP\Pays.txt" -Stream Creds -Value "MotDePasse"
Maintenant, si on affiche à nouveau la liste des streams de notre fichier, on obtient une nouvelle entrée :
Si l'on s'amuse à afficher le contenu de notre fichier, on verra que la valeur "MotDePasse" que je viens d'ajouter au fichier ne ressort pas.
Get-Content "C:\TEMP\Pays.txt"
D'ailleurs, pour consulter le flux par défaut, on peut préciser son nom à la suite du paramètre -Stream de Get-Content (attention à la syntaxe) :
Get-Content "C:\TEMP\Pays.txt" -Stream ':$DATA'
Si l'on veut afficher le contenu du stream "Creds" que l'on a créé précédemment, il suffit de le dire :
Get-Content "C:\TEMP\Pays.txt" -Stream Creds
La commande va retourner une seule valeur : MotDePasse
La preuve en image ci-dessous :
C'est à connaître, mais il ne faut pas non plus se dire que c'est la solution miracle pour cacher des mots de passe ou des données confidentielles. En fait, on peut scanner le système avec des outils spécifiques ou Get-ChildItem à la recherche de fichiers qui ont un stream supplémentaire que le $DATA par défaut.
C'est un peu hors sujet, mais pour effectuer cette analyse à partir d'un dossier courant comme point de départ :
Get-ChildItem -Recurse | ForEach { Get-Item $_.FullName -Stream * } | Where stream -ne ':$Data'
Cette commande fera ressortir notre fichier Pays.txt et son stream "Creds" ?. Il est fort possible des documents Office soient également mis en avant par la sortie de la commande avec un stream nommé "Zone.Identifier". Il contient un ID qui permet au système de connaître la zone d'appartenance de ce fichier (intranet, internet, etc.. vis-à-vis des zones IE).
Nous venons de voir, dans le détail, comment utiliser la commande Get-Content de PowerShell.