Home > Back-end >  Only remove empty sub-folders not root
Only remove empty sub-folders not root

Time:12-06

I was reading this post here: https://stackoverflow.com/a/28637537/800592

one of the comments mentions in order to not delete the root folder to do

 @bricktop if ($IsEmpty) { # only remove if it is not the root if ($Path -ne $InPath) { Write-Output ">> Deleting empty folder ${InPath}" Remove-Item -Force -LiteralPath $InPath } } 

BUT there's no where that sets the $InPath var ?? what am I missing here ?

CodePudding user response:

A simple solution adapted from the original answer is to pass a recursion-depth counter to the script block, which defaults to 0 and is incremented for every recursive call.

Thus, if the counter is 0, you know that you're dealing with the original input path, and you can ignore the attempt to delete that path itself:

$tailRecursion = {
  param(
    [string] $LiteralPath,
    [int] $Depth = 0  # Helper parameter for internal use that tracks the recursion depth.
  )
  # Recurse over subdirs.
  foreach ($childDirectory in Get-ChildItem -Force -LiteralPath $LiteralPath -Directory) {
    # Note the increment to the recursion depth with -Depth ($Depth   1)
    & $tailRecursion -LiteralPath $childDirectory.FullName -Depth ($Depth   1)
  }
  $isEmpty = -not (Get-ChildItem -Force -LiteralPath $LiteralPath | Select-Object -First 1)
  if ($isEmpty -and $Depth -gt 0) { # dir. is empty and NOT the input dir.
    Write-Verbose "Removing empty folder at path '${LiteralPath}'." -Verbose
    Remove-Item -Force -LiteralPath $LiteralPath -WhatIf
  }
}

# Sample call: delete all empty subdirs. in the current dir.'s
# subtree, without trying to delete the current dir itself, 
# should it turn to be empty too.
& $tailRecursion -LiteralPath .

Note: The -WhatIf common parameter in the command above previews the operation. Remove -WhatIf once you're sure the operation will do what you want.


Note that this alternative answer to the same question provides the desired functionality directly, and more elegantly; the only downside - which will rarely matter in practice - is increased memory consumption due to the up-front sorting of all directory-info objects.

Here's a slightly tweaked version:

# Uses . (the current dir.) as the sample input path.
Get-ChildItem -LiteralPath . -Recurse -Force -Directory | 
    Sort-Object -Property FullName -Descending |
    Where-Object { -not ($_ | Get-ChildItem -Force | Select-Object -First 1) } |
    Remove-Item -WhatIf

Note: The -WhatIf common parameter in the command above previews the operation. Remove -WhatIf once you're sure the operation will do what you want.

  • Related