سؤال

لدي حصة وهي "درج غير مرغوب فيه" للمستخدمين النهائيين. إنهم قادرون على إنشاء مجلدات ومجلدات فرعية كما يرون مناسبة. أحتاج إلى تنفيذ برنامج نصي لحذف الملفات التي تم إنشاؤها لأكثر من 31 يومًا.

لقد بدأت ذلك مع PowerShell. أحتاج إلى متابعة البرنامج النصي لحذف الملف عن طريق حذف المجلدات الفرعية التي أصبحت الآن فارغة. بسبب تعشيش المجلدات الفرعية ، أحتاج إلى تجنب حذف مقلع فرعي فارغ من الملفات ، ولكن يحتوي على مقلع فرعي تحته يحتوي على ملف.

علي سبيل المثال:

  • FILE3a يبلغ من العمر 10 أيام. FILE3 يبلغ من العمر 45 يومًا.
  • أرغب في تنظيف الهيكل لإزالة الملفات التي تزيد قيمتها عن 30 يومًا ، وحذف المجلدات الفرعية الفارغة.
C:\Junk\subfolder1a\subfolder2a\FILE3a

C:\Junk\subfolder1a\subfolder2a\subfolder3a

C:\Junk\subfolder1a\subfolder2B\FILE3b

نتيجة مرغوبة:

  • حذف: FILE3b, subfolder2B & subfolder3a.
  • يترك: subfolder1a, subfolder2a, ، و FILE3a.

يمكنني تنظيف الملفات بشكل متكرر. كيف أقوم بتنظيف المجلدات الفرعية دون حذف subfolder1a؟ (سيبقى المجلد "غير المرغوب فيه".

هل كانت مفيدة؟

المحلول

أود أن أفعل هذا في ممرين - حذف الملفات القديمة أولاً ثم الأطراف الفارغة:

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

هذا النوع من العمليات التجريبية تتمثل قوة خطوط الأنابيب المتداخلة في PowerShell والتي توضح المجموعة الثانية من الأوامر. يستخدم خط أنابيب متداخل لتحديد ما إذا كان أي دليل يحتوي على ملفات صفرية تحتها.

نصائح أخرى

بروح الإجابة الأولى ، إليك أقصر طريقة لحذف الدلائل الفارغة:

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

هناك حاجة إلى علامة -Force للحالات التي تكون فيها الدلائل مخفية ، مثل .SVN

سيؤدي ذلك إلى فرز الدلائل الفرعية قبل أن تعمل أدلة الوالدين حول مشكلة الدليل المتداخل الفارغ.

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

إضافة إلى آخر واحد:

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

هذا سيجعله يكتمل حيث سيستمر البحث في إزالة أي مجلدات فارغة تحت نقطة انطلاق $

كنت بحاجة إلى بعض الميزات الصديقة للمؤسسات. ها هو رأيي.

لقد بدأت بالرمز من إجابات أخرى ، ثم أضفت ملف JSON مع قائمة المجلدات الأصلية (بما في ذلك عدد الملفات لكل مجلد). إزالة الدلائل الفارغة وتسجيل تلك.

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.

لإزالة الملفات التي تزيد أعمارها عن 30 يومًا:

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

(فقط قم بإزالة ملف -whatif لأداء في الواقع.)

المتابعة مع:

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

هذا عمل بالنسبة لي.

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

$path = "C:\Some\Path"

حذف الملفات الأقدم من $limit:

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

حذف أي أدلة فارغة تركت وراءها بعد حذف الملفات القديمة:

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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top