que he conseguido hacer una macro que en realidad puede borrar archivos y carpetas vacías vacías dentro de una jerarquía de carpetas.
que me tomó un tiempo para tocar el violín a cabo, pero ahora funciona:
@ECHO OFF
SET topLevel=%cd%
FOR /D /R %%D IN (*) DO (
CD %%D
FOR %%F IN (*) DO IF %%~zF EQU 0 DEL "%%F"
)
CD %topLevel%
FOR /F "usebackq delims=" %%D IN (`"DIR/AD/B/S|SORT/R"`) DO RD "%%D"
Primero se desactiva haciendo eco (quitar @ECHO OFF si desea leer lo que realmente sucede). Luego almacena la carpeta actual en la variable topLevel. Lo siguiente es recorrer todas las carpetas "% D" utilizando el comando FOR en la carpeta actual y todas las subcarpetas. Cambia el directorio local a cada una de las subcarpetas encontradas (CD %% D). Dentro de cada subcarpeta usando otro bucle FOR encuentra y borra todos los archivos %% F para los cuales el tamaño del archivo (~ z para %% ~ zF) es 0. Cuando todo este bucle doble finaliza, todos los archivos vacíos son efectivamente eliminados del disco. Ahora se ejecuta un nuevo comando FOR para realizar un RD %% D para eliminar todos los directorios. Debido a que DOS está a salvo aquí, eliminará solo las carpetas VACÍAS. Las carpetas con archivos dentro se mantienen intactas.
Pero, ¿quién dice que no puede mejorar una vez más?
Hemos modificado la secuencia de comandos, una vez más, ahora muy optimizado paraprocesamiento rápido:
@ECHO OFF
SET topLevel=%CD%
FOR /D /R %%D IN (*) DO (
CD %%D
CALL :innerLoop
)
CD %topLevel%
FOR /F "usebackq delims=" %%D IN (`"DIR /AD/B/S | SORT /R"`) DO RD "%%D"
GOTO :break
:innerLoop
FOR /F "delims=" %%F IN ('DIR/B/A-D/OS') DO IF %%~zF EQU 0 (DEL "%%F") ELSE (GOTO :break)
:break
El problema con el anterior era que los dos bucles for anidados tocado cada fila india. Como los archivos vacíos son raros, no hay absolutamente ninguna necesidad de tocar cada archivo y es una gran pérdida de tiempo. Intenté ejecutarlo en un volumen de 25 TByte con ~ 5 millones de archivos ...
Modifiqué el bucle interno para ordenar archivos por tamaño en un comando DIR utilizando la opción/OS (Tamaño ordenado). La opción/A-D no muestra directorios, por lo que solo quedan archivos verdaderos (los directorios también se muestran como tamaño 0, por eso lo agregué). Para cada archivo, se verifica el tamaño. Una vez que se encuentra un archivo de más de 0 bytes, el ciclo se cierra usando GOTO: break. Como los archivos están ordenados por tamaño, el más pequeño primero, es seguro proceder de esta manera. ¡Un gran ahorro de tiempo!
Como el comando DOS FOR no tiene una forma elegante de abandonar el bucle, utilicé este extraño constructo para llamar al bucle interno usando GOTO: break.
parece correr sobre unos pocos miles de veces más rápido en mi gran volumen que el anterior ;-)
espero que les guste!
Saludos, Axel Mertes
PS: La pesadilla más grande en el DOS es la comprensión de secuencias de comandos cuando se necesita o %%%, 'o "etc.
Hmmm ... Así que pensé en esto también , usando un bucle for para solo una iteración en mi archivo. Esperaba que haya algo más elegante que esto, pero esto servirá. – Xonatron
@MatthewDoucette Agregué una alternativa usando CALL en lugar de FOR – dbenham
@MatthewDoucette - He agregado aún otro método usando FINDSTR.También arreglé un error tonto en la solución CALL (demasiados puntos en la etiqueta). – dbenham