Comment supprimer des sous-dossiers vides avec PowerShell?

j'ai une part qui est un "tiroir poubelle" pour les utilisateurs finaux. Ils sont capables de créer des dossiers et des sous-dossiers comme ils le souhaitent. J'ai besoin d'implémenter un script pour supprimer les fichiers de plus de 31 jours.

j'ai commencé avec Powershell. Je dois suivre le script de suppression de fichier en supprimant les sous-dossiers qui sont maintenant vides. En raison de l'imbrication de sous-dossiers, je dois éviter de supprimer un sous-dossier qui est vide de fichiers, mais a un sous-dossier sous elle qui contient un fichier.

Par exemple:

  • FILE3a a 10 jours. <!-Il a 45 jours.
  • je veux nettoyer la structure en supprimant les fichiers de plus de 30 jours, et supprimer les sous-dossiers vides.
C:Junksubfolder1asubfolder2aFILE3a

C:Junksubfolder1asubfolder2asubfolder3a

C:Junksubfolder1asubfolder2BFILE3b

résultat Souhaité:

  • Supprimer: FILE3b,subfolder2B& subfolder3a.
  • Quitter: subfolder1a,subfolder2a et FILE3a.

je peux nettoyer recursivement les fichiers. Comment puis-je nettoyer les sous-dossiers sans supprimer <!--6? (Le dossier "Junk" restera toujours.)

27
demandé sur Tshepang 2009-10-16 02:29:15

7 réponses

je voudrais faire en deux étapes - supprimer les anciens fichiers en premier et ensuite le vide dirs:

Get-ChildItem -recurse | Where {!$_.PSIsContainer -and `
$_.LastWriteTime -lt (get-date).AddDays(-31)} | Remove-Item -whatif

Get-ChildItem -recurse | Where {$_.PSIsContainer -and `
@(Get-ChildItem -Lit $_.Fullname -r | Where {!$_.PSIsContainer}).Length -eq 0} |
Remove-Item -recurse -whatif

ce type d'opération met en évidence la puissance des pipelines imbriqués dans PowerShell, ce qui est démontré par la seconde série de commandes. Il utilise un pipeline imbriqué pour déterminer de façon récursive si un répertoire a zéro fichiers sous lui.

42
répondu Keith Hill 2010-07-22 15:13:29

Dans l'esprit de la première réponse, ici, c'est le chemin le plus court pour supprimer les répertoires vides:

ls -recurse | where {!@(ls -force $_.fullname)} | rm -whatif

L'indicateur de force est nécessaire pour les cas où les répertoires ont des dossiers cachés, comme .svn

9
répondu Bogdan Calmac 2010-11-20 18:29:46

cela va trier les sous-répertoires avant les répertoires parents travaillant autour du problème de répertoire imbriqué vide.

dir -Directory -Recurse |
    %{ $_.FullName} |
    sort -Descending |
    where { !@(ls -force $_) } |
    rm -WhatIf
4
répondu Doug Coburn 2017-06-17 16:23:25

ajouter au dernier:

while (Get-ChildItem $StartingPoint -recurse | where {!@(Get-ChildItem -force $_.fullname)} | Test-Path) {
    Get-ChildItem $StartingPoint -recurse | where {!@(Get-ChildItem -force $_.fullname)} | Remove-Item
}

cela le rendra complet où il continuera à chercher Pour supprimer tous les dossiers vides sous le point $StartingPoint

3
répondu bbo 2012-05-15 14:47:38

j'avais besoin de quelques fonctionnalités conviviales pour l'entreprise. Voici mon point de vue.

j'ai commencé avec le code d'autres réponses, puis j'ai ajouté un fichier JSON avec la liste originale des dossiers (y compris le nombre de dossiers par dossier). Supprimé les répertoires vides et enregistrer les.

https://gist.github.com/yzorg/e92c5eb60e97b1d6381b

param (
    [switch]$Clear
)

# if you want to reload a previous file list
#$stat = ConvertFrom-Json (gc dir-cleanup-filecount-by-directory.json -join "`n")

if ($Clear) { 
    $stat = @() 
} elseif ($stat.Count -ne 0 -and (-not "$($stat[0].DirPath)".StartsWith($PWD.ProviderPath))) {
    Write-Warning "Path changed, clearing cached file list."
    Read-Host -Prompt 'Press -Enter-'
    $stat = @() 
}

$lineCount = 0
if ($stat.Count -eq 0) {
    $stat = gci -Recurse -Directory | %{  # -Exclude 'Visual Studio 2013' # test in 'Documents' folder

        if (++$lineCount % 100 -eq 0) { Write-Warning "file count $lineCount" }

        New-Object psobject -Property @{ 
            DirPath=$_.FullName; 
            DirPathLength=$_.FullName.Length;
            FileCount=($_ | gci -Force -File).Count; 
            DirCount=($_ | gci -Force -Directory).Count
        }
    }
    $stat | ConvertTo-Json | Out-File dir-cleanup-filecount-by-directory.json -Verbose
}

$delelteListTxt = 'dir-cleanup-emptydirs-{0}-{1}.txt' -f ((date -f s) -replace '[-:]','' -replace 'T','_'),$env:USERNAME

$stat | 
    ? FileCount -eq 0 | 
    sort -property @{Expression="DirPathLength";Descending=$true}, @{Expression="DirPath";Descending=$false} |
    select -ExpandProperty DirPath | #-First 10 | 
    ?{ @(gci $_ -Force).Count -eq 0 } | %{
        Remove-Item $_ -Verbose # -WhatIf  # uncomment to see the first pass of folders to be cleaned**
        $_ | Out-File -Append -Encoding utf8 $delelteListTxt
        sleep 0.1
    }

# ** - The list you'll see from -WhatIf isn't a complete list because parent folders
#      might also qualify after the first level is cleaned.  The -WhatIf list will 
#      show correct breath, which is what I want to see before running the command.
2
répondu yzorg 2014-03-14 16:59:18

pour supprimer les fichiers de plus de 30 jours:

get-childitem -recurse |
    ? {$_.GetType() -match "FileInfo"} |
    ?{ $_.LastWriteTime -lt [datetime]::now.adddays(-30) }  |
    rm -whatif

(il suffit de supprimer le