Get-Childitem est une commande Powershell permettant de récuperer l'intégralité des fichiers et dossiers dans un répertoire, et ce de manière récursive. Afin de connaître l'origine des problèmes d'espace disque sur notre partie NAS, j'ai crée un script utilisant Get-Childitem pour obtenir la taille de l'espace personnel de chaque utilisateur, et en ressortir les 3 fichiers les plus imposants.

Seul problème, certains repertoires étant profondéments ancrés dans une hierarchie tentaculaire de dossiers et sous-dossiers, leur nom complet devenait extrêmement long, et Powershell -qui rappelons-le, se base sur .NET- est limité à une longueur de 260 caractères sur le chemin complet.

SOLUTION DE CONTOURNEMENT

Pour contourner cela et obtenir la liste complète des fichiers, il faut utiliser un outil bien connu dans le monde de la copie windows, ROBOCOPY.

En utilisant cet outil intégré dans Windows 7, nous pouvons obtenir une liste de fichiers via un outil n'utilisant pas .NET, et outrepassant donc cette limitation à 260 caractères.

Le problème de ROBOCOPY est que son format de retour est une chaîne de texte difficilement exportable sous format tableau. Nous allons donc utiliser les Expressions Regulières (REGEX) pour formater chaque ligne et la séparer de manière intelligente. Tout d'abord, voici un format de ligne renvoyé par ROBOCOPY.

robocopy

Nous voyons qu'il y'a une série d'espaces, suivi de la taille du fichier, la date, un espace, l'heure, une série d'espaces, le nom du fichier (pouvant comporter un nombre indéfini d'espaces et de caractères divers).

Et voici la REGEX correspondante pour hacher proprement , que j'expliquerais ensuite.

$files[30] -match "\d+\s\S+\s\S+\s+.*$"

Attendez avant de prendre une aspirine! Je sais que cela semble particulièrement imbuvable, mais vous allez voir qu'en fait, les expressions régulières sont à la fois faciles à comprendre et puissantes!

Chaque lettre signifie quelque chose. Dans cette expression nous avons :

  • \d qui signifie "n'importe quel chiffre"
  • \s qui signifie "n'importe quel caractère vide (espace, tabulation, espace insécable)
  • \S qui signifie "tout ce qui n'est pas caractère vide"
  • un "point" qui signifie "tout caractère"
  • $ qui précise la fin de la ligne

Et quand au + et * ?!

Et bien ce sont les symboles qui précisent le nombre d'itérations que l'on doit trouver sur l'objet accolé. Le + signifie "une occurence ou plus" et le * "zéro occurence ou plus". Il est tout à fait possible de préciser un nombre d'itérations, en les mettant entre crochets, par exemple \d{2}.

Si l'on reprend notre format de ligne renvoyé par Robocopy, nous constatons effectivement que nous avons \d+ (un nombre de chiffres indéfini) suivi d'un \s (espace), puis \S+ pour des caractères non vides , de nouveau \s+ pour un nombre inconnu d'espaces, et enfin le restant .*$ , n'importe quel caractère jusqu'a la fin de la ligne.

Bon, maintenant que nous savons comment hacher cela, comment récuperer les informations? Et bien c'est simple... lorsque l'on se sert de l'opérateur -Match , les résultats valides de l'expression sont sauvegardés dans une variable nommée $Matches, comme ici :

gci

Mais cet affichage n'est pas vraiment interessant, car il ne nous renvoie que l'intégralité de la correspondance du REGEX. Comment pouvons-nous donc différencier le tout? Par le biais d'une syntaxe spécifique, de ce format :

(?<nombre>\d{2})

Dans cet exemple, nous enregistrerons dans "nombre" les deux chiffres à l'emplacement donné. Reprenons l'exemple ci dessus, mais en enregistrant cette fois ci la découpe du REGEX, grace à l'expression suivante :

"(?<premier>\w+)\s(?<deuxieme>\w+)"

Observons maintenant le résultat dans $Matches :

gci2

Et désormais c'est très facile d'appeler une partie de la découpe du REGEX :

gci3

Maintenant, en appliquant cela à notre exemple de Robocopy, nous pouvons facilement detecter la taille, la date du fichier, ainsi que son chemin complet, à l'aide d'une REGEX pour laquelle, j'en suis persuadé ( :) ) , vous trouverez aisément la signification :

"(?<taille>\d+)\s(?<date>\S+\s\S+)\s+(?<chemin>.*$)"

Voici la réponse, pour celles et ceux qui n'auraient pas deviné :

gci4

Vous êtes désormais capable de dépasser cette limitation de caractères ennuyeuse venant du .NET ! Pour une documentation plus complète des quantifieurs et des classes de caractères pour les Regex, une seule direction : MSDN! Et comme personne n'aime chercher, voici les liens pour vous!

Lien sur les quantifieurs.

Lien sur les classes de caractères.

Ajouter un commentaire

Article précédent Article suivant