3

I have a Visual Studio solution with several projects. I clean up the bin and obj folders as part of clean up using the following script.

Get-ChildItem -path source -filter obj -recurse | Remove-Item -recurse
Get-ChildItem -path source -filter bin -recurse | Remove-Item -recurse

This works perfectly. However, I have a file-based data folder that has about 600,000 sub folders in it and is located in a folder called FILE_DATA.

The above script takes ages because it goes through all these 600,000 folders.

I need to avoid FILE_DATA folder when I recursively traverse and remove bin and obj folders.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user1145404
  • 285
  • 1
  • 3
  • 9

2 Answers2

3

Here is a more efficient approach that does what you need--skip subtrees that you want to exclude:

function GetFiles($path = $pwd, [string[]]$exclude)
{
    foreach ($item in Get-ChildItem $path)
    {
        if ($exclude | Where {$item -like $_}) { continue }

        $item
        if (Test-Path $item.FullName -PathType Container)
        {
            GetFiles $item.FullName $exclude
        }
    }
} 

This code is adapted from Keith Hill's answer to this post; my contribution is one bug fix and minor refactoring; you will find a complete explanation in my answer to that same SO question.

This invocation should do what you need:

GetFiles -path source -exclude FILE_DATA

For even more leisurely reading, check out my article on Simple-Talk.com that discusses this and more: Practical PowerShell: Pruning File Trees and Extending Cmdlets.

Community
  • 1
  • 1
Michael Sorens
  • 35,361
  • 26
  • 116
  • 172
  • This has solved my problem. I made little changes to make it work for me. I'll post my code soon. Thank you. – user1145404 Jan 21 '13 at 23:58
  • function RemoveBinAndObj($path = $pwd, [string[]]$remove, [string[]]$exclude) { foreach ($item in Get-ChildItem $path) { if ($exclude | Where {$item -like $_}) { continue } if ($remove | Where {$item -like $_}) { Write-Host "Removing " + $item.FullName Remove-Item $item.FullName -Recurse } if (Test-Path $item.FullName -PathType Container) { RemoveBinAndObj $item.FullName $remove $exclude } } } – user1145404 Jan 22 '13 at 14:49
  • Sorry, but Graimer has a more concise and best solution. Your solution works perfectly too. It solves the problem. But Graimer's solution is more concise and also executes faster. – user1145404 Jan 22 '13 at 15:47
  • Since you now state that you are interested just in immediate children then I agree--@Graimer's special case solution is more appropriate. My solution addresses the more general scenario of any descendants, not just immediate children. – Michael Sorens Jan 22 '13 at 16:17
2

If the FILE_DATA folder is a subfolder of $source (not deeper), try:

$source = "C:\Users\Frode\Desktop\test"
Get-Item -Path $source\* -Exclude "FILE_DATA" | ? {$_.PSIsContainer} | % {
    Get-ChildItem -Path $_.FullName -Filter "obj" -Recurse | Remove-Item -Recurse
    Get-ChildItem -Path $_.FullName -Filter "bin" -Recurse | Remove-Item -Recurse
}
Frode F.
  • 52,376
  • 9
  • 98
  • 114
  • The folder is a grand sub folder from source. This works..but it still goes inside FILE_DATA folder. – user1145404 Jan 21 '13 at 23:53
  • grand subfolder? ex. `$source = c:\test` and `FILE_DATA is c:\test\FILE_DATA`? – Frode F. Jan 22 '13 at 07:07
  • tested it now. it didn't delete FILE_DATA when I used `$source = c:\test` but when running PS 2.0 it didn't care about `-Include` so it delete pretty much everything else :P Fixed it now – Frode F. Jan 22 '13 at 14:57
  • For those who just want to delete all `bin` and `obj` folders in their solution's project folders, simply replace the first line by `Get-ChildItem -Directory | % {` (the -Directory flag is part of PowerShell 3). If you want to delete `bin` and `obj` only from immediate children, drop the `-Recurse` flag before the pipe. Also, `-Path $_.FullName` can be shortened to `$_`. – Oliver May 30 '14 at 11:21