Question

J'ai une part qui est un « tiroir d'ordure » pour les utilisateurs finaux. Ils sont capables de créer des dossiers et sous-dossiers comme ils l'entendent. Je dois mettre en application un script pour supprimer les fichiers créés de plus de 31 jours.

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

Par exemple:

  • FILE3a est de 10 jours. FILE3 est de 45 jours.
  • Je veux nettoyer la structure en supprimant les fichiers de plus de 30 jours, et supprimer des sous-dossiers vides.
C:\Junk\subfolder1a\subfolder2a\FILE3a

C:\Junk\subfolder1a\subfolder2a\subfolder3a

C:\Junk\subfolder1a\subfolder2B\FILE3b

Résultat souhaité:

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

Je peux récursive nettoyer les fichiers. Comment puis-je nettoyer les sous-dossiers sans supprimer subfolder1a? (Le dossier "indésirable" restera toujours.)

Était-ce utile?

La solution

Je ferais cela en deux passes - supprimer les anciens fichiers d'abord, puis les dirs vides:

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 démo du pouvoir de pipelines imbriqués dans PowerShell lequel le second ensemble de commandes démontre. Il utilise un pipeline imbriqué pour déterminer si un répertoire récursive a zéro des fichiers en dessous.

Autres conseils

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

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

Le drapeau -force est nécessaire pour les cas où les répertoires ont des dossiers cachés, comme .svn

triera les sous-répertoires avant répertoires parents qui travaillent autour du problème de répertoire imbriqué vide.

dir -Directory -Recurse |
    %{ $_.FullName} |
    sort -Descending |
    where { !@(ls -force $_) } |
    rm -WhatIf

Ajout à la dernière:

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

Il sera complète où il continuera de chercher à supprimer tous les dossiers vides sous la startingpoint $

Je avais besoin des fonctionnalités conviviales entreprise. Voici ma prise.

J'ai commencé avec le code d'autres réponses, puis ajouté un fichier JSON avec la liste des dossiers d'origine (y compris le nombre de fichiers par dossier). Suppression des répertoires vides et connectez-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.

Pour supprimer des fichiers de plus de 30 jours:

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

(Il suffit de retirer le -whatif pour effectuer réellement.)

Suivi avec:

 get-childitem -recurse |
     ? {$_.GetType() -match "DirectoryInfo"} |
     ?{ $_.GetFiles().Count -eq 0 -and $_.GetDirectories().Count -eq 0 } |
     rm -whatif

Cela a fonctionné pour moi.

$limit = (Get-Date).AddDays(-15) 

$path = "C:\Some\Path"

Supprimer les fichiers plus anciens que le $limit:

Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force

Supprimez tous les répertoires vides laissés après la suppression des anciens fichiers:

Get-ChildItem -Path $path -Recurse -Force | Where-Object { $_.PSIsContainer -and (Get-ChildItem -Path $_.FullName -Recurse -Force | Where-Object { !$_.PSIsContainer }) -eq $null } | Remove-Item -Force -Recurse
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top