Regex à la rescousse de Get-ChildItem

Imaginons le problème suivant.

Nous voulons que Get-ChildItem nous retourne les éléments de deuxième niveau, d’une arborescence de répertoires.

Par exemple je peux avoir un répertoire racine C:\TEMP, dans lequel il y a C:\TEMP\LEVEL1 et dans lequel il y a un autre répertoire C:\TEMP\LEVEL1\LEVEL2.

Et bien je voudrais trouver le moyen avec Get-ChildItem de ne récupérer que les répertoires de deuxième niveau en dessous d’un répertoire racine donné.

Lorsque je tombe sur ce type de problématique j’appelle les expressions régulières (REGEX) à la rescousse.

Les Regex sont un langage dans le langage, et surtout un moyen très puissant pour analyser une chaine de caractères.

Créons notre regex:

La chaine de caractères que nous voulons matcher avec notre regex est la suivante: ‘ C:\TEMP\LEVEL1\LEVEL2’.

Il faut la décomposer (mentalement) pour trouver des délimiteurs. Le délimiteur naturel d’une arborescence est le caractère ‘\’ (backslash). Donc nous avons:

x\x\x\x où x est une chaine de caractères arbitraire. Mais attention pas simplement du alphanumérique, car on peut trouver le caractère ‘:’ par exemple. Et le nom d’un répertoire peut contenir des espaces. On peut traduire x avec ‘.*’ qui veut dire, ‘.’ n’importe quel caractère, et ‘*’ répété n fois.

On commence un regex par ^ ce qui signifie début de chaine de caractères. ^ peut aussi vouloir dire not si utilisé au milieu d’une chaine, mais dans notre cas on ne s’en servira pas ainsi.

Du coup pour matcher C:\TEMP nous pouvons écrire ‘^.*\\.*$’

Le ‘$’ veut dire fin de phrase.

Le double backslash sert à dire que nous voulons vraiment un backslash dans la chaine. Le backslash étant un moyen d’indiquer des caractères spécifiques, \s est un string, \d est un chiffre, \t est un Tab, \n est nouvelle ligne, \0 est le null character utilisé en C pour finir une chaine de caractères. Du coup si nous voulons un \ nous devons en mentionner deux.

Voici le regex complet:

La structure du code est la suivante:

Nous faisons un appel à Get-ChildItem en indiquant un répertoire racine, et en indiquant -recurse pour récupérer les répertoires enfants. Ensuite on ‘pipe’ le résultat vers la cmdlet Where-Object où on analysera le nom de chaque élément avec notre regex.

Finalement on ‘pipe’ le résultat vers ForEach-Object où l’on pourra traiter chaque élément de façon individuelle avec la référence $_.

Voici le code complet:

  • Si

    Le problème de cette démarche est que tous les objets du répertoires et des sous répertoires sont lus et pas seulement ceux du niveau voulus.

    • Oui, Get-ChildItem récupère tous les fichiers, donc cette approche est plutôt un moyen de filtrer ce qui est remonté.