Script to delete files and folders older than X days

I wish to run a script daily that will delete folders and respective files in it which are older than X days (for my webcam recordings). I have the following script, though when run, files are not deleted.

# Enter a number to indicate how many days old the identified file needs to be (must have a "-" in front of it).
$HowOld = -1

#Path to the root folder
$Path = "E:\CAMMEDIA"

#Deletion task
get-childitem $Path -recurse | where {$_.lastwritetime -lt (get-date).adddays($HowOld) -and -not $_.psiscontainer} |% {remove-item $_.fullname -force -whatif}

Powershell screenshot

I also created a Task Scheduler Task; the following is in the argument section:

-ExecutionPolicy Bypass c:\scripts\myscript.ps1 -RunType $true -Path E:\CAMMEDIA


Your script has a -WhatIf, which will not delete the files, only report what will be done. If you remove the -WhatIf, does the script work manually? If the script works manually, then the next question is what user is running the script in the scheduled task?

Thanks @Rob. If I simply remove the whatif statement, nothing happens.

I discovered, I need to replace -whatif with -verbose.

Here’s what I ended up with…

#Days older than
$HowOld = -1

#Path to the root folder
$Path = "E:\CAMMEDIA"

#Deletion files task
get-childitem $Path -recurse | where {$_.lastwritetime -lt (get-date).adddays($HowOld) -and -not $_.psiscontainer} |% {remove-item $_.fullname -force -verbose}

#Deletion empty folders task
do {
  $dirs = gci $Path -directory -recurse | Where { (gci $_.fullName -Force).count -eq 0 } | select -expandproperty FullName
  $dirs | Foreach-Object { Remove-Item $_ }
} while ($dirs.count -gt 0)

You are over complicating it. Try something like this:

#Days older than
$HowOld = -1

#Path to the root folder
$Path = "E:\CAMMEDIA"

#Get the files to delete
$filesToDelete = Get-ChildItem -Path $Path -File -Recurse | Where {$_.lastwritetime -lt (Get-Date).AddDays($HowOld)}

#Delete the files
$filesToDelete | Remove-Item -Force -WhatIf

Most Powershell cmdlets that Accept Pipeline Input, which will automatically loop through each of the objects passed to it. If you run the following…

Get-Help Remove-Item -Full

you will see the path, which is also required, accepts…

-Path Specifies a path of the items being removed. Wildcard characters are permitted.
    Required?                    true
    Position?                    0
    Default value                None
    Accept pipeline input?       True (ByPropertyName, ByValue)
    Accept wildcard characters?  false

You can run the first 3 lines to see if you are collecting the files and then use the prompt to validate the files:

PS C:\Users\Rob> #Days older than
$HowOld = -1

#Path to the root folder
$Path = $env:Temp

#Get the files to delete
$filesToDelete = Get-ChildItem -Path $Path -File -Recurse | Where {$_.lastwritetime -lt (Get-Date).AddDays($HowOld)}

PS C:\Users\Rob> $filesToDelete.Count

PS C:\Users\Rob> $filesToDelete | Select -First 3

    Directory: C:\Users\Rob\AppData\Local\Temp

Mode                LastWriteTime         Length Name                                                                                                                                                                                                
----                -------------         ------ ----                                                                                                                                                                                                
-a----         5/2/2018  12:55 PM              0 aria-debug-15216.log                                                                                                                                                                                
-a----         5/2/2018  12:47 PM              0 aria-debug-17600.log                                                                                                                                                                                
-a----         5/2/2018  12:52 PM            470 aria-debug-1844.log                                                                                                                                                                                 

I get the following message/error:

Remove-Item : Cannot bind argument to parameter 'Path' because it is null.
At line:1 char:10
+ $files | Remove-Item -Force
+          ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Remove-Item], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.RemoveItemC

I think line 11 of the original code by Rob should be:

$filesToDelete | Remove-Item -Force -WhatIf

Oops, wrong variable. Ivan is the man!

Okay, that seems to work. To go live, should I remove the whatif statement now? Do I need to replace whatif with verbose?

Another way…

# Enter a number to indicate how many days old the identified file needs to be 
$HowOld = '1' 
#Path to the root folder
$Path = "E:\CAMMEDIA"

#Deletion task
get-childitem $Path -recurse -file | where { (get-date) - $_.lastwritetime -gt $HowOld } | 
  remove-item -force -verbose

Remove -WhatIf will delete the files, performing the operation. If you are looking for logging, you can do use the -Verbose switch or just add $filesToDelete to the script to enumerate or something like:

 $filesToDelete | Select FullName

@js, I couldn’t get this to work.

Weird. Take off the period. I corrected the code. I’m trying to make $HowOld automatically cast to a [timespan] of one day.

# One day, the first is a floating point:

# Error:

# One tick: