PowerShell: Commandes pour manipuler les formats de fichiers

Les formats de fichiers produits par les commandes PowerShell sont parfois déroutants.

Pourtant les exemples trouvés sur le web sont souvent simplistes car ils ne reflètent pas toujours la complexité de la réalité.

En effet, les « vrais » fichiers recèlent des pièges liés aux données elles-mêmes: présence de virgule ou de point-virgule dans les données au format CSV, etc.

Cet article est l’occasion de passer en revue les principales particularités des formats de fichier et les commandes associées.

Out-File

Pour obtenir la liste des services qui s’exécutent sur votre ordinateur dans un fichier texte, vous allez utiliser la commande Out-File.

Ouvrez une invite de commande PowerShell en tant qu’Administrateur et tapez:

Get-WmiObject win32_service | Out-File .services.txt

Ouvrez le fichier services.txt avec Notepad++:

ExitCode : 0
Name : AdobeARMservice
ProcessId : 1780
StartMode : Auto
State : Running
Status : OK

ExitCode : 0
Name : AdobeFlashPlayerUpdateSvc
ProcessId : 0
StartMode : Manual
State : Stopped
Status : OK

Dans ce cas, vous ne récupérez qu’une partie des informations d’un service, la disposition est sous forme de fiche et le fichier est encodé en UCS-2 Little Endian.

Encodage UTF-8

Pour avoir un encodage UTF-8, tapez:

Get-WmiObject win32_service | Out-File .services.txt -Encoding « UTF8 »

Par défaut, Get-WmiObject win32_service produit un résultat sous forme de liste. Pour avoir une disposition tabulaire, vous essayez:

Get-WmiObject win32_service | Format-Table | Out-File .services.txt -Encoding « UTF8 »

Le résultat:

ExitCode Name ProcessId StartMode State Status
——– —- ——— ——— —– ——
0 AdobeARMservice 1780 Auto Running OK
0 AdobeFlashPlayer… 0 Manual Stopped OK

Le « Name » est partiel. La mise en forme est peu pratique pour un traitement automatisé.

Commande Get-Service

Le résultat ne vous convenant toujours pas, vous changez de commande pour obtenir la liste des services. Au lieu d’utiliser Get-WmiObject win32_service, vous essayez la commande Get-Service qui par défaut produit un résultat sous forme de tableau:

Get-Service | Out-File .services.txt -Encoding « UTF8 »

Le résultat est encore différent:

Status Name DisplayName
—— —- ———–
Running AdobeARMservice Adobe Acrobat Update Service
Stopped AdobeFlashPlaye… Adobe Flash Player Update Service

En fait, la colonne Name (ainsi que DisplayName) est tronquée.

Export-Csv

Au lieu d’utiliser Out-File, vous allez utiliser Export-Csv. Tapez la commande suivante:

Get-WmiObject win32_service | Export-Csv .services.csv -Encoding « UTF8 »

Ouvrez le fichier services.csv avec Notepad++ et vous voyez apparaître beaucoup plus d’informations sous forme quasi-tabulaire:

#TYPE System.Management.ManagementObject#rootcimv2Win32_Service
« PSComputerName », »__GENUS », »__CLASS », »__SUPERCLASS », »__DYNASTY », »__RELPATH »,…
« MONORDINA », »2″, »Win32_Service », »Win32_BaseService », »CIM_ManagedSystemElement », »Win32_Service.Name= » »AdobeARMservice » » »,…
« MONORDINA », »2″, »Win32_Service », »Win32_BaseService », »CIM_ManagedSystemElement », »Win32_Service.Name= » »AdobeFlashPlayerUpdateSvc » » »,…

Pour éliminer la première ligne (« #TYPE System.Management.ManagementObject#rootcimv2Win32_Service »), il suffit de rajouter le paramètre -NoTypeInformation à la ligne de commande:

Get-WmiObject win32_service | Export-Csv .services.csv -Encoding « UTF8 » -NoTypeInformation

Ouvrez le fichier services.csv avec Microsoft Office Excel. Lors de son ouverture, Excel a détecté la présence du séparateur « ; » dans certaines lignes et il a séparé les données concernées dans la seconde colonne (« B »). Par exemple la description du « Service de cache de police Windows » contient un « ; »: « […] Il peut être désactivé ; il en résulte cependant une dégradation des performances des applications. »

Délimiteur spécifique

La présence inopportune du séparateur « ; » va rendre plus complexe le traitement des données lors de l’utilisation d’un Split(). Aussi, pour contourner ce problème, vous décidez de changer de délimiteur en choisissant un caractère plus rare comme ¤.

La commande devient:

Get-WmiObject win32_service | Export-Csv .services.csv -Delimiter « ¤ » -Encoding « UTF8 » -NoTypeInformation

Lorsque vous ouvrez le fichier services.csv avec Microsoft Office Excel, celui-ci n’arrive pas à séparer les colonnes automatiquement: l’assistant d’importation de texte se lance.

Assistant d'importation de texte d'Excel

Vous pouvez réduire le nombre de colonnes avec l’utilisation de la commande Select-Object. Par exemple, si vous ne voulez que le nom et la description (« Caption ») de chaque service, vous tapez la commande suivante:

Get-WmiObject win32_service | Select-Object Name, Caption | Export-Csv .services.csv -Delimiter « ¤ » -Encoding « UTF8 » -NoTypeInformation

Le fichier résultat est plus sobre:

« Name »¤ »Caption »
« AdobeARMservice »¤ »Adobe Acrobat Update Service »
« AdobeFlashPlayerUpdateSvc »¤ »Adobe Flash Player Update Service »

Import-Csv

Pour retraiter le fichier résultat, utilisez la commande PowerShell Import-CSV suivante:

Import-Csv .services.csv -Delimiter « ¤ »

Commande PowerShell Import-Csv

Pour traiter une seule colonne, vous utilisez la fonction Split() ou la variable automatique $_.

La commande suivante fournit la description de tous les services dont le nom débute avec la lettre « A »:

Import-Csv .services.csv -Delimiter « ¤ » | ForEach-Object {if($_.Name.StartsWith(« A »)){write-host $_.Caption}}

Si votre fichier services.csv ne possédait pas d’entête, la commande précédente échouerait. Pour y remédier, il suffit d’indiquer un entête dans la commande Import-Csv avec le paramètre Header:

Import-Csv .services.csv -Header (« Name », »Caption ») -Delimiter « ¤ » | ForEach-Object {if($_.Name.StartsWith(« A »)){write-host $_.Caption}}

Le résultat donne quelque chose comme:
Adobe Acrobat Update Service
Adobe Flash Player Update Service

Supprimer les double guillemets

Lorsque vous utilisez Export-CSV, cette commande ajoute automatiquement des guillemets autour de chaque donnée retournée. Pour enlever tous les guillemets des fichiers CSV à l’aide de PowerShell, l’article de Hey, Scripting Guy! donne une solution qui combine l’utilisation des commandes Export-Csv et Out-File. Toutefois, cette solution n’est pas pleinement satisfaisant car elle remplace aussi les guillemets qui seraient à l’intérieur d’une donnée !

(Get-Content .services.csv) -replace ‘ »‘, «  » | Out-File .services.csv -Encoding « UTF8 » -Force

Faites attention à l’affichage ambigüe des guillemets et des quotes dans WordPress. L’opérateur -replace a comme premier argument ‘ »‘, soit: une quote, un guillemet, une quote.
Le second argument est «  », soit: un guillemet, un guillemet.

La paramètre -Force permet d’écraser un fichier en lecture seule.

Une solution moins radicale consiste à utiliser une expression régulière avec la fonction replace pour supprimer uniquement les guillemets en début et en fin de chaîne de chaque donnée: ‘^ »(.*) »$’, ‘$1’. Le replacement doit se faire sur chaque donnée, et non pas ligne par ligne.

Tableaux / Arrays

Face à la diversité des choix, vous pouvez être tenté de manipuler toutes les données à l’aide de tableaux (« Arrays ») plutôt que de les stocker temporairement dans un fichier.

Si le volume de données manipulées n’est pas disproportionné, ce choix est souvent judicieux car la manipulation en mémoire reste souvent plus rapide que l’écriture sur un disque dur.

Toutefois, pour des raisons de conservations d’historique ou de traçabilité, vous devrez peut-être enregistrer les données manipulées dans un fichier.

Dans ce cas, n’utilisez pas l’opérateur -replace sur les objets. En effet, les commandes suivantes risquent de produire un résultat différent de vos attentes:

# Génére un fichier CSV à partir de la liste des services de l’ordinateur
Get-WmiObject win32_service | Select-Object Name, Caption | Export-Csv .services.csv -Delimiter « ¤ » -Encoding « UTF8 » -NoTypeInformation

# Alimente le tableau $Array à partir du fichier CSV
$Array = Import-Csv .services.csv -Delimiter « ¤ »

# Cherche à remplacer des caractères dans $Array puis génère un fichier TXT pour récupérer le résultat
$Array -replace « Adobe », »ADOBE » | Out-File .services-2.txt

# Cherche à remplacer des caractères dans $Array puis génère un second fichier CSV pour récupérer le résultat
$Array -replace « Adobe », »ADOBE » | Export-Csv .services-2.csv -Delimiter « ¤ » -NoTypeInformation

Le contenu de services-2.txt:

@{Name=ADOBEARMservice; Caption=ADOBE Acrobat Update Service}
@{Name=ADOBEFlashPlayerUpdateSvc; Caption=ADOBE Flash Player Update Service}

Le contenu de services-2.csv:

« Length »
« 61 »
« 76 »

L’opérateur -replace a converti l’objet tableau $Array en une seule chaine de caractères (string).

le fichier résultat services-2.txt contient les chaînes de caractères.

Le fichier résultat services-2.csv contient la longueur des chaînes de caractères. La chaîne « @{Name=ADOBEARMservice; Caption=ADOBE Acrobat Update Service} » fait exactement 61 caractères et la chaîne « @{Name=ADOBEFlashPlayerUpdateSvc; Caption=ADOBE Flash Player Update Service} » fait exactement 76 caractères.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *