7

I'm having problems to create a PS command that allows me to delete several subfolders without deleting the roof folder.

I.E:

C:\Test has many subfolders:

  • C:\Test\Item1
  • C:\Test\Item2
  • C:\Test\Item3

And the folders Item1, Item2 and Item3 have many subfolders and files.

I would like to create a PS that would allow me to delete all the empty subfolders inside Item1, Item2 and Item3 without deleting Item1, Item2 and Item3 folders. It is possible that any of the Item folders is empty, but I don't want to delete them, just the empty content of each folder.

This is just an example, I have a have around 300 Item folders inside Test.

I usually would use this:

$path="C:\TEST"

do {
   $dir = gci $path -directory -recurse | Where { (gci $_.fullName).count -eq 0 } | select -expandproperty FullName

   $dir | Foreach-Object { Remove-Item $_ }
} while ($dir.count -gt 0)

But this deletes the folder root folder (Item1, Item2 or Item3) if they are empty.

Thanks in advance.

1 Answer 1

23

So you are looking to delete All Items inside Empty Subfolders or all items in General?

This will delete all Folders or Items in General inside of the Directory "C:\abc\"

$path = "C:\abc\"
Get-ChildItem -Path $path -Recurse| Foreach-object {Remove-item -Recurse -path $_.FullName }

This will delete all Folders that dont have any items in them.

$path = "C:\abc\"
Get-ChildItem -Path $path -Recurse | Where-Object {(Get-ChildItem $_.FullName).Count -eq 0} |Foreach-object {Remove-item -Recurse -path $_.FullName }

´ This will look inside "C:\abc\" Get all the children and delete all empty Directories inside the Children in your example this would be Item1,Item2,...

$Path = "C:\abc\"
$itemFolders= Get-ChildItem -Path $Path
$itemFolders| Foreach-Object {
    Get-ChildItem -Path $_.FullName |
    Where-Object {(Get-ChildItem $_.FullName).Count -eq 0} | 
    Foreach-object {Remove-item -Recurse -path $_.FullName }
}

Just a quick and dirty bit of Code as I dont have much time, hope I could be of help.

EDIT: Here is what i came up with, its not as performant as I'd like but it gets the job done and is fairly quick, try it out for yourself it worked for me - even threw in a couple of comments and output to clarify what's going on.

$Path="C:\abc\"
$itemFolders = Get-ChildItem $Path
#Get All Folders inside
$AllFolders = $itemFolders | Get-ChildItem -Recurse | Where-Object {$_.PSIsContainer} | Select -Property FullName
#First delete all files older than 30 days
$itemFolders | Get-ChildItem -Recurse -File | ForEach-Object{
    $limit = (Get-Date).AddDays(-30)
    if($_.LastWriteTime -lt $limit)
    {
        "{0} hasn't been modified in the last 30 days deleting it" -f $_.FullName
        Remove-Item -Path $_.FullName -Force -ErrorAction SilentlyContinue        
    }
}
#Check if there are files inside that are not containers
$AllFolders | ForEach-Object{
    $files = Get-ChildItem -File -Recurse -Path $_.FullName
    $directories = Get-ChildItem -Directory -Recurse -Path $_.FullName

    #If There are any files inside the folder dont delete it.
    if($files.Count -gt 0)
    {
        "Found {0} files inside {1} do not delete this" -f $files.Count, $_.FullName
    }
    #If There are no files and no directories inside delete it.
    elseif($files.Count -eq 0 -and $directories.Count -eq 0)
    {
        "Empty Folder {0} deleting it" -f $_.FullName
        Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
    }
    #If there are no files and empty directories inside delete it.
    elseif($files.Count -eq 0 -and $directories.Count -gt 0)
    {
        "No Files but directories found in {0} since its recursive delete it" -f $_.FullName
        Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue        
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the response, this helped me since it's almost what I want. Thing is when a folder (For example Item1) has other subfolders that are empty, the PS won't delete them. If there's a way to achieve this it would be awesome. Thanks a lot!!!
Another thing I could use is to delete every file and folder inside the Item1.. ItemZ folders if they are older than X amount of time. Could that make things easier? What I don't want is to delete the ItemX folders.
Fule Little update here: I've managed to delete ALL files, but when I try to only delete the ones older than X amount of days, it doesn't work: $Path = "C:\Test\" $itemFolders= Get-ChildItem -Path $Path $limit = (Get-Date).AddDays(-30) $itemFolders| Foreach-Object { Get-ChildItem -Path $_.FullName | Where-Object {((Get-ChildItem $_.FullName).Count -ge 0) -or ($_.CreationTime -lt $limit)} | Foreach-object {Remove-item -Recurse -Force -path $_.FullName} }
The first one doesn't work, it outputs bunch of errors and nothing is deleted: "Remove-Item : A positional parameter cannot be found that accepts argument 'C:\Code\repos\zzz\rep\widgets\suites.json'."
Worked great! Only issue I'm having is wild cards in the file names. I looked into -LiteralPath on different script and it semi worked. Thinking I could add an error catcher for them and use -LiteralPath only on those files? Remove-Item : Cannot retrieve the dynamic parameters for the cmdlet. The specified wildcard character pattern is not valid: SK9Z$[EDJW{{K@TZ(L43ML7.png

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.