ise how commands comandos powershell window

how - ¿Cómo eliminar recursivamente todas las carpetas vacías en PowerShell?



windows powershell ise (6)

Necesito eliminar de forma recursiva todas las carpetas vacías para una carpeta específica en PowerShell (carpeta y subcarpeta checing en cualquier nivel).

En este momento estoy usando este script sin éxito.

¿Podría por favor decirme cómo solucionarlo?

$tdc=''C:/a/c/d/' $a = Get-ChildItem $tdc -recurse | Where-Object {$_.PSIsContainer -eq $True} $a | Where-Object {$_.GetFiles().Count -eq 0} | Select-Object FullName

Estoy usando PowerShell en Win 8.1


Debe tener en cuenta algunas cosas clave cuando se trata de un problema como este:

  1. Get-ChildItem -Recurse realiza la recursión de la cabeza, lo que significa que devuelve las carpetas tan pronto como las encuentra al caminar por un árbol. Ya que desea eliminar las carpetas vacías y también eliminar sus padres si están vacías después de eliminar las carpetas vacías, necesita usar la recursión de cola, que procesa las carpetas desde el niño más profundo hasta la raíz. Al usar la recursión de la cola, no habrá necesidad de llamadas repetidas al código que elimina las carpetas vacías, una llamada lo hará todo por usted.
  2. Get-ChildItem no devuelve archivos o carpetas ocultos de forma predeterminada. Como resultado, debe realizar pasos adicionales para asegurarse de no eliminar las carpetas que aparecen vacías pero que contienen archivos o carpetas ocultos. Get-Item y Get-ChildItem tienen un parámetro -Force que se puede usar para recuperar archivos o carpetas ocultos, así como archivos o carpetas visibles.

Con esos puntos en mente, aquí hay una solución que usa la recursión de la cola y que rastrea correctamente los archivos o carpetas ocultos, asegurándose de eliminar las carpetas ocultas si están vacías y también asegurándose de mantener las carpetas que pueden contener uno o más archivos ocultos

# First create some test data under C:/a (make sure this is not # a directory you care about, because this will remove it if it # exists). This test data contains a directory that is hidden # that should be removed as well as a file that is hidden in a # directory that should not be removed. Remove-Item -Force -Path C:/a -Recurse New-Item -Force -Path C:/a/b/c/d -ItemType Directory > $null $hiddenFolder = Get-Item -Force -LiteralPath C:/a/b/c $hiddenFolder.Attributes = $hiddenFolder.Attributes -bor [System.IO.FileAttributes]::Hidden New-Item -Force -Path C:/a/b/e -ItemType Directory > $null New-Item -Force -Path C:/a/f -ItemType Directory > $null New-Item -Force -Path C:/a/f/g -ItemType Directory > $null New-Item -Force -Path C:/a/f/h -ItemType Directory > $null Out-File -Force -FilePath C:/a/f/test.txt -InputObject ''Dummy file'' Out-File -Force -FilePath C:/a/f/h/hidden.txt -InputObject ''Hidden file'' $hiddenFile = Get-Item -Force -LiteralPath C:/a/f/h/hidden.txt $hiddenFile.Attributes = $hiddenFile.Attributes -bor [System.IO.FileAttributes]::Hidden # Now define a script block that will remove empty folders under # a root folder, using tail-recursion to ensure that it only # walks the folder tree once. -Force is used to be able to process # hidden files/folders as well. $tailRecursion = { param( $Path ) foreach ($childDirectory in Get-ChildItem -Force -LiteralPath $Path -Directory) { & $tailRecursion -Path $childDirectory.FullName } $currentChildren = Get-ChildItem -Force -LiteralPath $Path $isEmpty = $currentChildren -eq $null if ($isEmpty) { Write-Verbose "Removing empty folder at path ''${Path}''." -Verbose Remove-Item -Force -LiteralPath $Path } } # Lastly invoke the script block and pass in a root path where # you want it to start. This will remove all empty folders in # the folder you specify, including empty folders that contain # nothing but empty folders, including the start folder if that # winds up as empty. & $tailRecursion -Path ''C:/a''


La eliminación recursiva de subdirectorios vacíos también se puede lograr usando un "For Loop".

Antes de comenzar, hagamos algunos subdirectorios y archivos de texto para trabajar en $ HOME / Desktop / Test

MD $HOME/Desktop/Test/0/1/2/3/4/5 MD $HOME/Desktop/Test/A/B/C/D/E/F MD $HOME/Desktop/Test/A/B/C/DD/EE/FF MD $HOME/Desktop/Test/Q/W/E/R/T/Y MD $HOME/Desktop/Test/Q/W/E/RR "Hello World" > $HOME/Desktop/Test/0/1/Text1.txt "Hello World" > $HOME/Desktop/Test/A/B/C/D/E/Text2.txt "Hello World" > $HOME/Desktop/Test/A/B/C/DD/Text3.txt "Hello World" > $HOME/Desktop/Test/Q/W/E/RR/Text4.txt

Primero, almacene el siguiente bloque de script en la variable $ SB. La variable se puede llamar más tarde usando el comando & SB. El comando & SB generará una lista de subdirectorios vacíos contenidos en $ HOME / Desktop / Test

$SB = { Get-ChildItem $HOME/Desktop/Test -Directory -Recurse | Where-Object {(Get-ChildItem $_.FullName -Force).Count -eq 0} }

NOTA: El parámetro -Force es muy importante. Se asegura de que los directorios que contienen archivos y subdirectorios ocultos, pero que por lo demás estén vacíos, no se eliminen en "For Loop".

Ahora use un "For Loop" para eliminar recursivamente los subdirectorios en $ HOME / Desktop / Test

For ($Empty = &$SB ; $Empty -ne $null ; $Empty = &$SB) {Remove-Item (&$SB).FullName}

Probado como trabajando en PowerShell 4.0


Puedes usar esto:

$tdc="C:/a/c/d" $dirs = gci $tdc -directory -recurse | Where { (gci $_.fullName).count -eq 0 } | select -expandproperty FullName $dirs | Foreach-Object { Remove-Item $_ }

$dirs será una matriz de directorios vacíos devueltos por el comando Get-ChildItem después del filtrado. A continuación, puede recorrer sobre él para eliminar los elementos.

Actualizar

Si desea eliminar los directorios que contienen directorios vacíos, solo debe seguir ejecutando el script hasta que desaparezcan. Puedes hacer un bucle hasta que $dirs esté vacío:

$tdc="C:/a/c/d" do { $dirs = gci $tdc -directory -recurse | Where { (gci $_.fullName).count -eq 0 } | select -expandproperty FullName $dirs | Foreach-Object { Remove-Item $_ } } while ($dirs.count -gt 0)

Si desea asegurarse de que los archivos y carpetas ocultos también se eliminarán, incluya el indicador -Force :

do { $dirs = gci $tdc -directory -recurse | Where { (gci $_.fullName -Force).count -eq 0 } | select -expandproperty FullName $dirs | Foreach-Object { Remove-Item $_ } } while ($dirs.count -gt 0)


Si solo quiere asegurarse de eliminar solo las carpetas que pueden contener subcarpetas, pero no los archivos dentro de sí y sus subcarpetas, esto puede ser más fácil y rápido.

$Empty = Get-ChildItem $Folder -Directory -Recurse | Where-Object {(Get-ChildItem $_.FullName -File -Recurse -Force).Count -eq 0} Foreach ($Dir in $Empty) { if (test-path $Dir.FullName) {Remove-Item -LiteralPath $Dir.FullName -recurse -force} }


Suponiendo que estás dentro de la carpeta principal de interés

gci . -Recurse -Directory | % { if(!(gci -Path $_.FullName)) {ri -Force -Recurse $_.FullName} }

Para tu caso con $tdc será

gci $tdc -Recurse -Directory | % { if(!(gci -Path $_.FullName)) {ri -Force -Recurse $_.FullName} }


ls c:/temp -rec |%{ if ($_.PSIsContainer -eq $True) {if ( (ls $_.fullname -rec | measure |select -expand count ) -eq "0" ){ ri $_.fullname -whatif} } }