3

C:\Temp\ifc has about 297 folders inside it with roughly 4.1 million files spread amongst them.

Using a script I found elsewhere on this site, I wrote the following to delete all 'files' which are older than 1 hour.

$TargetFolder = “C:\Temp\ifc”
$NumberRange = "-1"
Get-ChildItem $TargetFolder -Recurse | Where {$_.lastwritetime -lt (Get-Date).AddHours($NumberRange)} | Remove-Item

The problem I am having is that it is deleting the sub-folders as well (if these folders end up with no files in them).

What can I add to this so that it leaves the folder structure in place?

Many Thanks.

1 Answer 1

6

You could add an additional where clause to ignore folders like this:

Where-Object{!($_.PSIsContainer)}

In the code snippet above;

  • ! means not,
  • $_ means current value of object in the pipe,
  • PSIsContainer is a property of the current object that returns true or false depending on if it is a folder or not.

So !($_.PSIsContainer) means current value of object in pipe is not a folder,
which is evaluated by Where-Object{}

Then your script would be like this:

$TargetFolder = “C:\Temp\ifc\”
$NumberRange = "-1"
Get-ChildItem $TargetFolder -Recurse | Where-Object{!($_.PSIsContainer)} | Where {$_.lastwritetime -lt (Get-Date).AddHours($NumberRange)} | Remove-Item

Another approach is to ignore the folders at the call to Get-ChildItem using the -File parameter like this:

$TargetFolder = “C:\Temp\ifc\”
$NumberRange = "-1"
Get-ChildItem $TargetFolder -File -Recurse | Where {$_.lastwritetime -lt (Get-Date).AddHours($NumberRange)} | Remove-Item

This approach has the benefit of returning the file objects at a sooner point in the execution cycle and making the command line shorter. Depending on the number of objects in the path, this may also have a measurable speed improvement.

5
  • 1
    Or, if you've a recentish Powershell, Get-ChildItem $TargetFolder -Recurse -File ... so you can get files only before you hit the pipeline.
    – jscott
    Mar 6, 2016 at 1:28
  • Where-Object{!($_.PSIsContainer)} worked perfectly, not sure what it means so must go do some Googling :) Mar 6, 2016 at 21:53
  • ! means not, $_ means current value of object in the pipe, PSIsContainer means is a folder. So !($_.PSIsContainer) means current value of object in pipe is not a folder which is fed into Where-Object{}
    – Tim Penner
    Mar 6, 2016 at 22:03
  • i expanded the answer a bit, i hope this makes things more clear
    – Tim Penner
    Mar 6, 2016 at 22:20
  • Remember that in v2 or v3, the Get-ChildItem cmdLet added switches "-file" and "-directory". Easier to type than "where {$_.psIsContainer -eq $something }"
    – Clayton
    Mar 7, 2016 at 14:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.