简体   繁体   中英

Filter and delete files and folders(and files inside of folders) older than x days in powershell

this is my first post on this forum. Im a beginner in coding and I need help with one of my very first self coded tools. I made a small script, which deletes files based on if they are older than date x (lastwritetime). Now to my problem: I want the script also to check for files inside of folders inside of a directory and only delete a folder afterwards if it is truly empty. I cant figure out how to solve the recursion in this problem, seems like the script deletes just the entire folder in relation to the date x. Could anyone tell me please what I missed in this code and help me to create a own recursion to solve the problem or fix the code? Thanks to you all, guys: Here is my code:

I would be glad if someone knows how to make the code work by using a function


$path = Read-Host "please enter your path"
"
"

$timedel = Read-Host "Enter days in the past (e.g -12)"

$dateedit = (Get-Date).AddDays($timedel)
"
"
Get-ChildItem $path -File -Recurse | foreach{ if ($_.LastWriteTime -and !$_.LastAccessTimeUtc -le $dateedit) {

Write-Output "older as $timedel days: ($_)" } }

" 
"
pause

Get-ChildItem -Path $path -Force -Recurse | Where-Object { $_.PsisContainer -and $_.LastWriteTime -le $dateedit } | Remove-Item -Force -Recurse 

""
Write-Output "Files deleted"

To also remove folders that are older than the set days in the past if they are empty leaves you with the problem that as soon as a file is removed from such a folder, the LastWriteTime of the folder is set to that moment in time.

This means you should get a list of older folders first, before you start deleting older files and use that list afterwards to also remove these folders if they are empty.

Also, a minimal check on user input from Read-Host should be done. (ie the path must exist and the number of days must be convertable to an integer number. For the latter I chose to simply cast it to [int] because if that fails, the code would generate an execption anyway.

Try something like

$path = Read-Host "please enter your path"
# test the user input
if (-not (Test-Path -Path $path -PathType Container)) {
    Write-Error "The path $path does not exist!" 
}
else {
    $timedel = Read-Host "Enter days in the past (e.g -12)"

    # convert to int and make sure it is a negative value
    $timedel  = -[Math]::Abs([int]$timedel)
    $dateedit = (Get-Date).AddDays($timedel).Date  # .Date sets this date to midnight (00:00:00)

    # get a list of all folders (FullNames only)that have a LastWriteTime older than the set date.
    # we check this list later to see if any of the folders are empty and if so, delete them.
    $folders = (Get-ChildItem -Path $path -Directory -Recurse | Where-Object { $_.LastWriteTime -le $dateedit }).FullName

    # get a list of files to remove
    Get-ChildItem -Path $path -File -Recurse | Where-Object { $_.LastWriteTime -le $dateedit} | ForEach-Object {
        Write-Host "older as $timedel days: $($_.FullName)" 
        $_ | Remove-Item -Force -WhatIf  # see below about the -WhatIf safety switch
    }

    # now that old files are gone, test the folder list we got earlier and remove any if empty
    $folders | ForEach-Object {
        if ((Get-ChildItem -Path $_ -Force).Count -eq 0) {
            Write-Host "Deleting empty folder: $_" 
            $_ | Remove-Item -Force -WhatIf  # see below about the -WhatIf safety switch
        }
    }

    Write-Host "All Done!" -ForegroundColor Green
}

The -WhatIf switch used on Remove-Item is there for your own safety. With that, no file or folder is actually deleted, instead in the console it is written what would be deleted. If you are satisfied that this is all good, remove the -WhatIf and run the code again to really delete the files and folders

param(
    [IO.DirectoryInfo]$targetTolder = "d:\tmp",
    [DateTime]$dateTimeX = "2020-11-15 00:00:00"
)

Get-ChildItem $targetTolder -Directory -Recurse | Sort-Object {$_.FullName} -Descending | ForEach-Object {
    Get-ChildItem $_ -File | Where-Object {$_.LastWriteTime -lt $dateTimeX} | Remove-Item -Force
    if ((Get-ChildItem $_).Count -eq 0){Remove-Item $_ -Force} 
}

remove -WhatIf after test

try something like this:

$timedel=-12

#remove old files
Get-ChildItem "C:\temp" -Recurse -File | Where LastWriteTime  -lt  (Get-Date).AddDays($timedel)  | Remove-Item -Force

#remove directory without file
Get-ChildItem "C:\temp\" -Recurse -Directory | where {(Get-ChildItem $_.FullName -Recurse -File).count -eq 0} | Remove-Item -Force -recurse

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM