Deleting Recycle Bin Items Deleted Over 28 Days Ago For All Users

This topic contains 14 replies, has 3 voices, and was last updated by  Jeff 10 months, 2 weeks ago.

  • Author
  • #51929


    I have a few different scripts that I have been using to remove items older than 28 days. However, I cannot find a way to do this for all users. I can use "last write time" in PowerShell for all users, but last write time is not the same as the deleted time. I found a script on that uses the "deleted time", but it only deletes the items for the current user (not all users on a machine). Does anyone know how I can achieve this? Script by D. Baldwin:

    # ----------------------------------------------------------------------- 
    #       Author    :   Baldwin D.
    #       Description : Empty Recycle Bin with Retention (Logoff Script)
    # -----------------------------------------------------------------------
    $Global:Collection = @()
    $Shell = New-Object -ComObject Shell.Application
    $Global:Recycler = $Shell.NameSpace(0xa)
    $csvfile = "\\YourNetworkShare\RecycleBin.txt"
    $LogFailed = "\\YourNetworkShare\RecycleBinFailed.txt"
    function Get-recyclebin
            $RetentionTime = "28",
        $User = $env:USERNAME
        $Computer = $env:COMPUTERNAME
        $DateRun = Get-Date
        foreach($item in $Recycler.Items())
            $DeletedDate = $Recycler.GetDetailsOf($item,2) -replace "\u200f|\u200e","" #Invisible Unicode Characters
            $DeletedDate_datetime = get-date $DeletedDate   
            [Int]$DeletedDays = (New-TimeSpan -Start $DeletedDate_datetime -End $(Get-Date)).Days
            If($DeletedDays -ge $RetentionTime)
                $Size = $Recycler.GetDetailsOf($item,3)
                $SizeArray = $Size -split " "
                $Decimal = $SizeArray[0] -replace ",","."
                If ($SizeArray[1] -contains "bytes") { $Size = [int]$Decimal /1024 }
                If ($SizeArray[1] -contains "KB") { $Size = [int]$Decimal }
                If ($SizeArray[1] -contains "MB") { $Size = [int]$Decimal * 1024 }
                If ($SizeArray[1] -contains "GB") { $Size = [int]$Decimal *1024 *1024 }
           $Object = New-Object Psobject -Property @{
                    Computer = $computer
                    User = $User
                    DateRun = $DateRun
                    Name = $item.Name
                    Type = $item.Type
                    SizeKb = $Size
                    Path = $item.path
                    "Deleted Date" = $DeletedDate_datetime
                    "Deleted Days" = $DeletedDays }
                    If ($DeleteItems)
                        Remove-Item -Path $item.Path -Confirm:$false -Force -Recurse
                        if ($?)
                            $Global:Collection += @($object)
                            Add-Content -Path $LogFailed -Value $error[0]
                    }#EndIf $DeleteItems
                }#EndIf($DeletedDays -ge $RetentionTime)
    }#EndForeach item
    Get-recyclebin -DeleteItems
    if (@($collection).count -gt "0")
    $Collection = $Collection | Select-Object "Computer","User","DateRun","Name","Type","Path","SizeKb","Deleted Days","Deleted Date"
    $CsvData = $Collection | ConvertTo-Csv -NoTypeInformation
    $Null, $Data = $CsvData
    Add-Content -Path $csvfile -Value $Data
  • #51938

    Dan Potter

    Never done it but I would think gci/remove-item would be much shorter than this script.

    Homework: Get-ChildItem "C:\`$Recycle.bin\" -Recurse -Force #apply a filter
    #pipe into remove-item

    • #51940


      I mentioned there are no properties to determine what the "deleted time" was for items in the Recycle Bin. I could only find "Last Write Time." I cannot use "last write time" because the requirement is to delete items that have been in the recycle bin for over 28 days (items deleted over 28 days ago). That is why I had to use the script above. However, that only deletes items for the current user.

    • #51948

      Dan Potter

      I don't know about your windows os but my lastwrite and deleted time match exactly.

  • #51946

    Dan Potter

    Looking into it further I'd probably translate the sids into user accounts prior to deletion for safety..It looks like there is a lot of program stuff in there. Also the names change, so the log isn't going to be useful.

  • #51950

    Dan Potter
  • #51959

    Dan Potter

    To get you started.

    gci "C:\`$Recycle.bin\" -Force | select mode,lastwritetime,name,@{n='aduser';e={(get-aduser $}} |ft
  • #52049

    Daniel Krebs

    Unfortunately, the deleted date information is not easily accessible. It is stored in info files next to the actual files.

    Get-ChildItem -Path 'C:\$Recycle.Bin\*\$I*' -Force

    I have yet to find a way to retrieve the information from these files without using the COM object which only works for the current user.

  • #52051

    Daniel Krebs

    The following PDF has an explanation of the $I file format on page 8 (right column).

  • #52057

    Dan Potter

    The deleted date is the lastwrite in the recycle bin. see above.

  • #52059

    Daniel Krebs

    Your observation is correct for the info files called $I(random).(original ext), but not for the original files which get moved and renamed to $R(same as info file).(original ext).

    • This reply was modified 11 months, 3 weeks ago by  Daniel Krebs.
    • #52087

      gci -Path "C:\`$Recycle.bin\" -Recurse -Force

      should be enough to find all files that need to be deleted for all users, right? That whole $I and $R files are interesting, but hoping I don't need to get that involved. If so, I can look further into that PDF. One thing that may be an issue is a machine with a secondary drive. If a file is deleted on that drive (e.g. E: drive), the recycle bin will be under E:\`$Recycle.bin\. I tried using a wildcard with the recycle bin, but that doesn't work.

  • #52077

    Dan Potter

    There is one R for every I right? If so, simple logic to tell when the item was deleted and remove both.

  • #54831


    I have just realized that the code below will not work since $I files and $R files do not match up. I will just end up deleting basically everything in the recycle bin.

    gci -Path "C:\`$Recycle.bin\" -Recurse -Force 

    The previous person mentioned "There is one R for every I right? If so, simple logic to tell when the item was deleted and remove both." This makes sense. However, I cannot figure out how to delete both the $I and $R files if the $I file is older than 28 days. The following code gives me the results I am searching for. however, I need to delete the corresponding $R files that have the same name as these $I files as well. Does anyone know how I can filter to both the $R and $I files when only the $I files have the correct date (last write time) that I'm looking for?

    Get-ChildItem -Path 'C:\`$Recycle.bin\' -Recurse -Force | ? { $_.Name -like '$I*' -and $_.LastWriteTime -lt (Get-Date).AddDays(-28) }

    This works as well:

    Get-ChildItem -Path 'C:\$Recycle.Bin\*\$I*' -Recurse -Force | ? { $_.LastWriteTime -lt (Get-Date).AddDays(-28) }

    I'm guessing I will need a foreach loop and some if statements. But I'm not sure how to find when the $I files match the $R file names. Any help would be appreciated.

  • #54834


    I think I finally figured it out

    $RetentionPeriod = (Get-Date).AddDays(-28)
    $Path = 'C:\$Recycle.Bin\*\$I*'
    # Find Recycle Bin items older than the $RetentionPeriod.
    $TargetItems = gci -Path $Path -Recurse -Force | ? { $_.LastWriteTime -lt $RetentionPeriod  }
    # Delete Recycle Bin items older than the $RetentionPeriod.
    Foreach ($Item in $TargetItems) {
        $ItemName = $Item.Name.Substring(2)
        Remove-Item "C:\`$Recycle.Bin\*\`$R$ItemName" -Force -Confirm:$false
        Remove-Item $Item.FullName -Force -Confirm:$false

    I am basically storing all files in scope in a variable that start with $I and am then deleting their matching $R files after cutting off the first two characters. Appears to be working. If anyone can think of a better way to do this, please feel free to chime in.

You must be logged in to reply to this topic.