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. Commented Mar 6, 2016 at 1:28
  • Where-Object{!($_.PSIsContainer)} worked perfectly, not sure what it means so must go do some Googling :) Commented 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{} Commented Mar 6, 2016 at 22:03
  • i expanded the answer a bit, i hope this makes things more clear Commented 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 }" Commented Mar 7, 2016 at 14:44

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.