Lorsqu’un serveur de fichiers commence à manquer d’espace disque, il peut être difficile d’identifier rapidement les répertoires responsables de cette consommation.
PowerShell permet d’automatiser cette analyse et d’obtenir en quelques commandes la taille des différents dossiers présents sur un partage ou un volume.
Dans ce tutoriel, nous allons construire progressivement un script capable d’analyser la taille des dossiers, de convertir les résultats en gigaoctets, de les trier et de les exporter dans un fichier CSV.
Objectif du tutoriel
À la fin de ce tutoriel, vous disposerez d’un script PowerShell permettant de :
- parcourir automatiquement les dossiers d’un emplacement ;
- calculer leur taille totale ;
- afficher leur taille en Go ;
- classer les dossiers du plus volumineux au plus petit ;
- exporter les résultats dans un fichier CSV ;
- identifier rapidement les répertoires nécessitant une analyse ou un nettoyage.
Prérequis
Ce tutoriel nécessite :
- Windows 10, Windows 11 ou Windows Server ;
- Windows PowerShell 5.1 ou PowerShell 7 ;
- des droits de lecture sur les dossiers analysés ;
- quelques notions de base sur PowerShell.
Pour analyser un serveur de fichiers distant, le compte exécutant le script doit également disposer des droits nécessaires sur le partage concerné.
⚠️ Attention
L’analyse d’une arborescence contenant plusieurs centaines de milliers de fichiers peut prendre du temps et générer de nombreuses opérations de lecture. Il est préférable d’effectuer les premiers tests sur un répertoire limité avant d’analyser un serveur de fichiers complet.
1. Définir le dossier à analyser
Commençons par indiquer à PowerShell l’emplacement contenant les dossiers que nous souhaitons analyser.
Dans cet exemple, nous utiliserons le dossier D:\Partages. Le chemin est enregistré dans une variable afin de pouvoir le modifier facilement par la suite.
$Chemin = "D:\Partages"
Get-ChildItem -Path $Chemin -Directory
La variable $Chemin contient le chemin du répertoire à analyser. La commande Get-ChildItem permet ensuite d’afficher son contenu.
Le paramètre -Path indique l’emplacement à parcourir, tandis que -Directory limite le résultat aux dossiers. Les fichiers présents directement dans D:\Partages ne sont donc pas affichés.
Analyser un partage réseau
Le même principe peut être utilisé avec un partage réseau en utilisant son chemin UNC :
$Chemin = "\\SRV-FICHIERS\Partages"
Get-ChildItem -Path $Chemin -Directory
💡 À retenir
Utiliser une variable pour stocker le chemin évite de modifier plusieurs lignes du script. Il suffira ensuite de changer la valeur de $Chemin pour analyser un autre emplacement.
2. Calculer la taille d’un dossier
Get-ChildItem nous permet maintenant d’identifier les dossiers présents dans l’emplacement à analyser. L’étape suivante consiste à parcourir leur contenu afin de calculer l’espace réellement occupé par leurs fichiers.
Pour comprendre le fonctionnement du script, commençons par calculer la taille d’un seul dossier.
Parcourir récursivement le contenu
Le paramètre -Recurse de Get-ChildItem permet de parcourir un dossier ainsi que l’ensemble de ses sous-dossiers.
$Dossier = "D:\Partages\Utilisateur1"
Get-ChildItem -Path $Dossier -File -Recurse
Dans cette commande :
-Path $Dossierindique le dossier à analyser ;-Filelimite les résultats aux fichiers ;-Recurseparcourt également tous les sous-dossiers.
PowerShell retourne ainsi la liste de tous les fichiers contenus dans l’arborescence.
Calculer la taille totale
Chaque fichier retourné par Get-ChildItem possède une propriété Length contenant sa taille en octets. Nous pouvons utiliser Measure-Object pour additionner toutes ces valeurs.
$Dossier = "D:\Partages\Utilisateur1"
$Taille = Get-ChildItem -Path $Dossier -File -Recurse |
Measure-Object -Property Length -Sum
$Taille.Sum
L’opérateur |, appelé pipeline, transmet les fichiers trouvés par Get-ChildItem à Measure-Object.
Measure-Object -Property Length -Sum additionne ensuite la propriété Length de chaque fichier. Le résultat est disponible dans $Taille.Sum.
Afficher la taille en Go
Le résultat obtenu est exprimé en octets, ce qui n’est pas très pratique pour un administrateur. PowerShell permet directement de convertir cette valeur en gigaoctets.
$TailleGo = [math]::Round($Taille.Sum / 1GB, 2)
$TailleGo
La valeur $Taille.Sum est divisée par 1GB, une constante reconnue nativement par PowerShell. [math]::Round(..., 2) arrondit ensuite le résultat à deux décimales. Par exemple, une taille de plusieurs milliards d’octets pourra ainsi être affichée simplement sous la forme : 12,47
💡 À retenir
Get-ChildItem récupère les fichiers, -Recurse parcourt toute l’arborescence et Measure-Object permet d’additionner leur propriété Length. La division par 1GB permet ensuite d’obtenir une valeur directement exploitable en gigaoctets.
ℹ️ Information
L’analyse peut afficher des erreurs si le compte utilisé ne possède pas les droits de lecture sur certains dossiers. Nous ajouterons plus loin une gestion des erreurs afin que le script puisse poursuivre son exécution sans être interrompu.
3. Analyser automatiquement tous les dossiers
Jusqu’à présent, nous avons calculé la taille d’un seul dossier. Sur un serveur de fichiers, cette méthode deviendrait rapidement fastidieuse s’il fallait modifier manuellement le chemin pour chaque répertoire.
Nous allons donc demander à PowerShell de récupérer automatiquement tous les dossiers présents dans notre emplacement de départ, puis d’effectuer le calcul pour chacun d’entre eux.
Parcourir chaque dossier
Nous pouvons reprendre la variable $Chemin définie précédemment et transmettre les dossiers trouvés à ForEach-Object.
$Chemin = "D:\Partages"
Get-ChildItem -Path $Chemin -Directory | ForEach-Object {
Write-Host "Analyse de $($_.FullName)"
}
Get-ChildItem -Directory récupère les dossiers situés directement dans D:\Partages.
Le pipeline | transmet ensuite chaque dossier à ForEach-Object. À l’intérieur de ce bloc, la variable automatique $_ représente le dossier actuellement traité.
La propriété FullName permet de récupérer son chemin complet.
ℹ️ Information
À ce stade, -Recurse n’est volontairement pas utilisé sur la première commande. Nous voulons mesurer les dossiers situés directement sous D:\Partages. C’est leur contenu qui sera ensuite parcouru récursivement.
Calculer la taille pendant le parcours
Nous pouvons maintenant intégrer le calcul précédent dans la boucle :
$Chemin = "D:\Partages"
Get-ChildItem -Path $Chemin -Directory | ForEach-Object {
$Taille = Get-ChildItem -Path $_.FullName -File -Recurse |
Measure-Object -Property Length -Sum
$TailleGo = [math]::Round($Taille.Sum / 1GB, 2)
Write-Host "$($_.Name) : $TailleGo Go"
}
Pour chaque dossier trouvé, PowerShell :
- parcourt tous ses fichiers et sous-dossiers ;
- additionne la taille des fichiers ;
- convertit le résultat en gigaoctets ;
- affiche le nom du dossier et sa taille totale.
Avec une arborescence contenant par exemple Comptabilite, Direction et RH, le résultat pourrait ressembler à :
Comptabilite : 18,42 Go
Direction : 7,81 Go
RH : 24,16 Go
Créer un objet PowerShell pour chaque résultat
Write-Host convient pour vérifier le fonctionnement du script, mais son résultat est peu exploitable. Pour pouvoir trier, filtrer ou exporter les données, il est préférable de créer de véritables objets PowerShell.
$Chemin = "D:\Partages"
$Resultats = Get-ChildItem -Path $Chemin -Directory | ForEach-Object {
$Taille = Get-ChildItem -Path $_.FullName -File -Recurse |
Measure-Object -Property Length -Sum
[PSCustomObject]@{
Dossier = $_.Name
Chemin = $_.FullName
TailleGo = [math]::Round($Taille.Sum / 1GB, 2)
}
}
$Resultats
[PSCustomObject] crée pour chaque dossier un objet contenant trois propriétés :
Dossier : le nom du répertoire analysé ;
Chemin : son chemin complet ;
TailleGo : l’espace occupé, arrondi à deux décimales.
Tous ces objets sont stockés dans la variable $Resultats.
✅ Bonne pratique
Privilégiez la création d’objets PowerShell à Write-Host lorsque les résultats doivent être réutilisés. Les objets peuvent ensuite être facilement triés, filtrés, exportés ou transmis à d’autres commandes.
4. Trier les dossiers du plus volumineux au plus petit
Notre variable $Resultats contient maintenant le nom, le chemin et la taille de chaque dossier. Pour identifier immédiatement les répertoires consommant le plus d’espace disque, nous pouvons trier ces objets avec Sort-Object.
$Resultats | Sort-Object -Property TailleGo -Descending
Sort-Object permet de classer les objets PowerShell selon une propriété.
Ici :
-Property TailleGoindique que le classement doit être effectué selon la taille ;-Descendingdemande un classement décroissant, du dossier le plus volumineux au plus petit.
Conserver le classement
Pour pouvoir réutiliser le classement dans la suite du script, nous pouvons enregistrer le résultat dans une nouvelle variable.
$ResultatsTries = $Resultats |
Sort-Object -Property TailleGo -Descending
$ResultatsTries
Dossier Chemin TailleGo
------- ------ --------
RH D:\Partages\RH 24,16
Comptabilite D:\Partages\Comptabilite 18,42
Direction D:\Partages\Direction 7,81
💡 À retenir
Le tri est réalisé sur la propriété numérique TailleGo et non sur le texte affiché. PowerShell peut donc correctement comparer les différentes tailles.
5. Exporter le rapport au format CSV
L’affichage dans la console est pratique pour une vérification rapide, mais un administrateur peut avoir besoin de conserver les résultats, de les transmettre ou de les exploiter dans Excel.
PowerShell permet d’exporter directement les objets contenus dans $ResultatsTries avec
Export-Csv.
$FichierCSV = "C:\Temp\Analyse-Dossiers.csv"
$ResultatsTries | Export-Csv `
-Path $FichierCSV `
-NoTypeInformation `
-Encoding UTF8
Dans cette commande :
- $FichierCSV définit l’emplacement du rapport ;
Export-Csvtransforme les objets PowerShell en données CSV ;-Pathindique le fichier à créer ;-NoTypeInformationévite l’ajout d’informations de type inutiles ;-Encoding UTF8utilise l’encodage UTF-8 pour le fichier généré.
Adapter le fichier CSV aux paramètres régionaux
La commande précédente génère un fichier CSV parfaitement exploitable. Cependant, le séparateur utilisé par défaut par Export-Csv n’est pas toujours celui attendu par les applications installées sur le poste.
Dans un environnement Windows configuré en français, Excel utilise généralement le point-virgule (;) comme séparateur de champs. Pour éviter d’avoir à préciser manuellement ce séparateur dans le script, PowerShell propose le paramètre -UseCulture.
Nous pouvons donc compléter notre commande d’export :
$ResultatsTries | Export-Csv `
-Path $FichierCSV `
-NoTypeInformation `
-Encoding UTF8 `
-UseCulture
Le paramètre -UseCulture demande à PowerShell d’utiliser le séparateur correspondant aux paramètres régionaux du système. Le script s’adapte ainsi automatiquement à la configuration du poste sur lequel il est exécuté.
ℹ️ Information
Sur un système Windows configuré en français, le séparateur de liste est généralement le point-virgule (;). Avec -UseCulture, le fichier CSV sera donc plus facilement exploitable dans Excel sans avoir à modifier manuellement le séparateur.
Exemple de fichier généré
"Dossier";"Chemin";"TailleGo"
"RH";"D:\Partages\RH";"24,16"
"Comptabilite";"D:\Partages\Comptabilite";"18,42"
"Direction";"D:\Partages\Direction";"7,81"
6. Vérifier la création du rapport
Nous pouvons terminer cette partie en affichant le chemin du rapport une fois l’export terminé.
Write-Host "Rapport généré : $FichierCSV"
Rapport généré : C:\Temp\Analyse-Dossiers.csv
7. Gérer les erreurs et les droits d’accès
Notre script fonctionne dans des conditions normales, mais plusieurs situations peuvent provoquer des erreurs lors de son exécution.
Sur un serveur de fichiers, certains répertoires peuvent notamment être protégés par des permissions NTFS spécifiques. Le dossier utilisé pour enregistrer le rapport peut également ne pas encore exister.
Nous allons donc améliorer le script afin qu’il puisse gérer ces situations sans interrompre inutilement son exécution.
Créer automatiquement le dossier de destination
Dans notre exemple, le rapport doit être enregistré dans C:\Temp. Si ce dossier n’existe pas, Export-Csv ne pourra pas créer le fichier.
Nous pouvons vérifier son existence avec Test-Path et le créer automatiquement si nécessaire.
$DossierRapport = "C:\Temp"
if (-not (Test-Path -Path $DossierRapport)) {
New-Item -Path $DossierRapport -ItemType Directory
}
$FichierCSV = Join-Path $DossierRapport "Analyse-Dossiers.csv"
Test-Path vérifie si C:\Temp existe.
L’opérateur -not inverse le résultat du test. Le bloc if est donc exécuté uniquement lorsque le dossier n’existe pas.
New-Item -ItemType Directory crée alors le répertoire.
Enfin, Join-Path construit proprement le chemin complet du fichier CSV à partir du dossier de destination et du nom du rapport.
✅ Bonne pratique
Utiliser Join-Path est préférable à la concaténation manuelle des chaînes de caractères pour construire des chemins. Le code est plus lisible et évite certains problèmes liés aux séparateurs de répertoires.
Traiter les erreurs d’accès
Lors du parcours récursif d’un serveur de fichiers, PowerShell peut rencontrer un dossier sur lequel le compte exécutant le script ne possède pas les droits de lecture nécessaires.
Plutôt que de simplement masquer ces erreurs, nous allons utiliser try et catch afin de les traiter explicitement.
try {
$Taille = Get-ChildItem -Path $_.FullName -File -Recurse -ErrorAction Stop |
Measure-Object -Property Length -Sum
$TailleGo = [math]::Round($Taille.Sum / 1GB, 2)
}
catch {
Write-Warning "Impossible d'analyser : $($_.Exception.Message)"
}
Par défaut, toutes les erreurs PowerShell ne provoquent pas nécessairement l’exécution du bloc catch.
Le paramètre -ErrorAction Stop demande ici à PowerShell de transformer l’erreur rencontrée en erreur bloquante pour la commande. Elle peut alors être interceptée par catch.
Le script peut ensuite décider de la manière dont cette erreur doit être traitée.
Conserver une trace des dossiers en erreur
try {
$Taille = Get-ChildItem -Path $_.FullName -File -Recurse -ErrorAction Stop |
Measure-Object -Property Length -Sum
[PSCustomObject]@{
Dossier = $_.Name
Chemin = $_.FullName
TailleGo = [math]::Round($Taille.Sum / 1GB, 2)
Statut = "OK"
}
}
catch {
[PSCustomObject]@{
Dossier = $_.Name
Chemin = $_.FullName
TailleGo = $null
Statut = "Analyse incomplète - accès refusé"
}
}
Nous ajoutons ici une nouvelle propriété Statut.
Lorsqu’un dossier est correctement analysé, sa valeur est OK. En cas d’erreur, le dossier reste présent dans les résultats, mais sa taille est laissée vide et son statut devient .Analyse incomplète - accès refusé
Cette méthode évite qu’un dossier inaccessible disparaisse silencieusement du rapport.
Dossier TailleGo Statut
RH 24,16 OK
Comptabilite 18,42 OK
Direction Erreur d'accès
⚠️ Attention
Une erreur d’accès ne signifie pas nécessairement que le script doit être exécuté avec un compte administrateur. Il est préférable d’accorder uniquement les droits de lecture nécessaires au compte utilisé pour l’analyse, conformément au principe du moindre privilège.
Vérifier le chemin à analyser
Avant de lancer l’analyse, il est également préférable de vérifier que le chemin défini dans $Chemin existe réellement.
if (-not (Test-Path -Path $Chemin -PathType Container)) {
Write-Error "Le chemin à analyser n'existe pas : $Chemin"
exit 1
}
Test-Path vérifie ici que le chemin existe et qu’il correspond bien à un dossier grâce à -PathType Container. Si ce n’est pas le cas, Write-Error affiche un message explicite et exit 1 arrête le script.
8. Le script PowerShell complet
Nous pouvons maintenant regrouper les différentes étapes précédentes dans un script unique.
Cette version analyse tous les dossiers situés directement dans un emplacement donné, calcule leur taille, gère les erreurs d’accès, trie les résultats du plus volumineux au plus petit et génère automatiquement un rapport CSV.
# ============================================================
# Analyse de la taille des dossiers
# ============================================================
# Emplacement à analyser
$Chemin = "D:\Partages"
# Emplacement du rapport
$DossierRapport = "C:\Temp"
# Vérification du chemin à analyser
if (-not (Test-Path -Path $Chemin -PathType Container)) {
Write-Error "Le chemin à analyser n'existe pas : $Chemin"
exit 1
}
# Création du dossier de destination si nécessaire
if (-not (Test-Path -Path $DossierRapport)) {
New-Item -Path $DossierRapport -ItemType Directory | Out-Null
}
# Construction du chemin du fichier CSV
$FichierCSV = Join-Path $DossierRapport "Analyse-Dossiers.csv"
# Analyse des dossiers
$Resultats = Get-ChildItem -Path $Chemin -Directory | ForEach-Object {
$Dossier = $_
try {
$Taille = Get-ChildItem -Path $Dossier.FullName `
-File `
-Recurse `
-ErrorAction Stop |
Measure-Object -Property Length -Sum
[PSCustomObject]@{
Dossier = $Dossier.Name
Chemin = $Dossier.FullName
TailleGo = [math]::Round($Taille.Sum / 1GB, 2)
Statut = "OK"
}
}
catch {
[PSCustomObject]@{
Dossier = $Dossier.Name
Chemin = $Dossier.FullName
TailleGo = $null
Statut = "Analyse incomplète - accès refusé"
}
}
}
# Tri du plus volumineux au plus petit
$ResultatsTries = $Resultats |
Sort-Object -Property TailleGo -Descending
# Affichage dans la console
$ResultatsTries | Format-Table -AutoSize
# Export du rapport
$ResultatsTries | Export-Csv `
-Path $FichierCSV `
-NoTypeInformation `
-Encoding UTF8 `
-UseCulture
Write-Host ""
Write-Host "Analyse terminée."
Write-Host "Rapport généré : $FichierCSV"
Une petite amélioration de lisibilité
Dans les exemples précédents, nous utilisions directement $_ pour représenter le dossier en cours de traitement.
Dans la version finale, celui-ci est enregistré dans la variable $Dossier :
$Dossier = $_
Nous pouvons ensuite utiliser $Dossier.Name et $Dossier.FullName. Cette écriture rend le script plus facile à lire et évite également toute ambiguïté lorsque d’autres blocs PowerShell, comme catch, utilisent leurs propres variables automatiques.
Adapter le script à votre environnement
Dans la plupart des cas, seules deux variables doivent être modifiées.
$Chemin = "\\SRV-FICHIERS\Partages"
$DossierRapport = "C:\Temp"
$Chemin peut contenir un chemin local ou un chemin UNC vers un partage réseau.
$DossierRapport définit l’emplacement dans lequel le fichier CSV sera enregistré.
Exemple de résultat
Après exécution, les résultats sont affichés dans la console et enregistrés dans le rapport CSV. Par exemple :
| Dossier | Chemin | Taille (Go) | Statut |
|---|---|---|---|
| RH | D:\Partages\RH | 24,16 | OK |
| Comptabilite | D:\Partages\Comptabilite | 18,42 | OK |
| Direction | D:\Partages\Direction | 7,81 | OK |
| Archives | D:\Partages\Archives | — | Analyse incomplète – accès refusé |
✅ Bonne pratique
Testez toujours le script sur une arborescence limitée avant de l’exécuter sur l’ensemble d’un serveur de fichiers. Sur un volume contenant plusieurs centaines de milliers ou millions de fichiers, l’analyse récursive peut être longue et générer une charge importante sur le stockage.
Cette première version fournit déjà un outil utilisable pour analyser ponctuellement l’occupation d’un serveur de fichiers.
PowerShell permet cependant d’aller plus loin : ajout de la date d’analyse dans le nom du rapport, journalisation des erreurs, comparaison de plusieurs analyses, détection des dossiers ayant fortement augmenté ou encore génération d’un rapport HTML.
Ces évolutions feront l’objet de prochains tutoriels consacrés à l’automatisation de l’administration système.
