Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursively Delete Files and Directories Using a Filter on the Directory Name

I am attempting to delete all directories, sub-directories, and the files contained in them based on a filter that specifies the required directory/sub-directory name.

For example, if I have c:\Test\A\B.doc, c:\Test\B\A\C.doc, and c:\Test\B\A.doc and my filter specifies all directories named 'A', I would expect the remaining folders and files to be c:\Test, c:\Test\B and c:\Test\B\A.doc respectively.

I am trying to do this in PowerShell and am not familiar with it.

The following 2 examples will delete all of the files that match my specified filter, but the files that match the filter as well.

$source = "C:\Powershell_Test" #location of directory to search
$strings = @("A")
cd ($source);
Get-ChildItem -Include ($strings) -Recurse -Force | Remove-Item -Force –Recurse

and

Remove-Item -Path C:\Powershell_Test -Filter A
like image 409
Liz Russell Avatar asked Sep 18 '25 22:09

Liz Russell


2 Answers

I would use something like this:

$source = 'C:\root\folder'
$names  = @('A')

Get-ChildItem $source -Recurse -Force |
  Where-Object { $_.PSIsContainer -and $names -contains $_.Name } |
  Sort-Object FullName -Descending |
  Remove-Item -Recurse -Force

The Where-Object clause restricts the output from Get-ChildItem to just folders whose names are present in the array $names. Sorting the remaining items by their full name in descending order ensures that child folders get deleted before their parent. That way you avoid errors from attempting to delete a folder that had already been deleted by a prior recursive delete operation.

If you have PowerShell v3 or newer you can do all filtering directly with Get-ChildItem:

Get-ChildItem $source -Directory -Include $names -Recurse -Force |
  Sort-Object FullName -Descending |
  Remove-Item -Recurse -Force
like image 197
Ansgar Wiechers Avatar answered Sep 21 '25 14:09

Ansgar Wiechers


I don't think you can do it quite that simply. This gets the list of directories, and breaks the path into its constituent parts, and verifies whether the filter matches one of those parts. If so, it removes the whole path.

It adds a little caution to handle if it already deleted a directory because of nesting (the test-path) and the -Confirm helps ensure that if there's a bug here you have a chance to verify the behavior.

$source = "C:\Powershell_Test" #location of directory to search
$filter = "A"
Get-Childitem -Directory -Recurse $source | 
    Where-Object { $_.FullName.Split([IO.Path]::DirectorySeparatorChar).Contains($filter) } |
    ForEach-Object { $_.FullName; if (Test-Path $_) { Remove-Item $_ -Recurse -Force -Confirm } }
like image 35
Matthew Wetmore Avatar answered Sep 21 '25 14:09

Matthew Wetmore