我设法制作了一个宏,它实际上可以删除文件夹层次结构中的空文件和空文件夹。
我花了一段时间才弄明白,但现在可以了:
@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"
它首先禁用回显(如果您想了解实际发生的情况,请删除 @ECHO OFF)。
然后它将当前文件夹存储在 topLevel 变量中。
接下来是在当前文件夹和所有子文件夹中使用 FOR 命令遍历所有文件夹“%D”。
它将本地目录更改为找到的每个子文件夹 (CD %%D)。
在使用另一个 FOR 循环的每个子文件夹中,它会查找并删除所有文件大小为 %%F 的文件(对于 %%~zF 的 ~z)为 0。
当整个双循环完成后,所有空文件都被有效地从磁盘中杀死。
现在执行一个新的 FOR 命令来执行 RD %%D 以删除每个目录。
由于 DOS 在这里是安全的,它只会删除 EMPTY 文件夹。包含文件的文件夹保持不变。
但是,谁说你不能再提高一次?
我再次修改了脚本,现在高度优化以实现快速处理:
@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
前一个的问题是两个嵌套的 FOR 循环触及了每个文件。由于空文件很少见,因此绝对没有必要触摸每个文件,这非常浪费时间。我尝试在 25 TByte 的卷上运行它,其中包含大约 500 万个文件。
所以我修改了内部循环,使用 /OS(Ordered Size)选项在 DIR 命令中按大小对文件进行排序。 /A-D 选项不列出目录,所以只保留真正的文件(目录也被列为大小 0,这就是我添加它的原因)。对于每个文件,都会检查大小。一旦找到大于 0 字节的文件,就使用 GOTO :break 退出循环。由于文件按大小排序,最小的在前,这样可以安全地进行。更安全!
由于 DOS FOR 命令没有优雅的方式离开循环,我使用这个奇怪的结构来调用内部循环,使用 GOTO :break。
在我的大音量上,它的运行速度似乎比上一个快几千倍 ;-)
希望你喜欢!
最好的问候,
阿克塞尔·默特斯
PS:DOS 脚本中最大的噩梦是理解何时需要 %% 或 %、' 或 " 等。