批处理 for 命令爬过的坑之在 Windows 命令行下显示目录大小
- 引子
- 一、入坑
- 二、延迟扩展
作者:高玉涵
时间:2023-1-5 17:08
环境:Windows 10 专业工作站版 22H2
引子
今天同事向我问了一个问题:在 Windows 命令行下显示目录大小。我很自然地在网络搜索并找到了这篇文章《在 Windows 命令行下显示目录大小》。囫囵吞枣般看了文章给出的示例代码,在转发给同事的同时还附上了一通自己的高谈。如,作者给出的 for 代码需要以硬编码的方式给出目录名和位置,这种方式缺乏灵活和通用性,应该将作者给出的代码嵌套在先遍历目录 for 命令内。思路是:先在当前路径下遍历出所有目录,再将目录名逐一传给嵌套的 for 命令以计算目录及子目录大小。
文章中的例子:
@echo off
set size=0
for /r %%x in (folder\*) do set /a size+=%%~zxecho %size% Bytes
修改后运行的样子:
@echo off
set size=0
for /r %%x in (db\*) do set /a size+=%%~zxecho %size% BytesC:\Dev>2.bat
260828 Bytes
如果你对这段代码比较陌生,可查看原作者的文章给出了详细解释。
一、入坑
先前已然在同事面前一顿高谈,不着手实现一下好像有点说不过去。下面是我的第一次尝试。
代码和运行后的样子:
@echo offset size=0
set sum=0for /d %%A in (*) do (@for /r %%B in ("%%A\*") do (set /a sum+=1set /a size+=%%~zB)echo %%A 有 %sum% 个文件,共有 %size% 字节set sum=0set size=0
)C:\Dev>3.bat
db 有 0 个文件,共有 0 字节
dootask 有 0 个文件,共有 0 字节
htdocs 有 0 个文件,共有 0 字节
ICS 有 0 个文件,共有 0 字节
nettool 有 0 个文件,共有 0 字节
python 有 0 个文件,共有 0 字节
route 有 0 个文件,共有 0 字节
shell-script 有 0 个文件,共有 0 字节
SMSBoom 有 0 个文件,共有 0 字节
tcpip 有 0 个文件,共有 0 字节
tyy 有 0 个文件,共有 0 字节
vue 有 0 个文件,共有 0 字节
vulhub 有 0 个文件,共有 0 字节
web 有 0 个文件,共有 0 字节
虽然我的程序贴心的给出了美观的输出。但,看到这样的结果,我懵了!
二、延迟扩展
当 CMD 读取每个命令行的时候,环境变量和带有 % 标记的命令行参数由它们对应的值所替代。然而,当你编写循环和复合 if 语句的时候,就可能引发一些不可预期的结果。
例如,先前的代码定义了 sum 和 size 变量,前者用于统计目录及子目录下所有文件数量
,后者用于统计它们总占用的大小。然而可惜的是,结果值都为无效的 0 。当 CMD 第一次遇到 for 语句的时候,它使用其定义的 0 替换了 %sum%、%size%。当 CMD 完成了 % 符号的处理,命令如下所示:
@echo offset size=0
set sum=0for /d %%A in (*) do (@for /r %%B in ("%%A\*") do (set /a sum+=1set /a size+=%%~zB)echo %%A 有 %0% 个文件,共有 %0% 字节set sum=0set size=0
)
由于在 for 循环开始运行之前, 0 值已经替换了,echo 不会看到 sum、size 值的修改,所以输出都是 0,而这根本不是你想要的结果。
有一种方法可以修正这一点:延迟扩展允许你用惊叹号来指定一个环境变量,而不是用百分号。表示只有当 CMD 实际想要执行该命令的时候,才扩展它们。由于 ! 在传统上并不是一个特殊字符,这一功能默认是关闭的。要打开延迟扩展,在 CMD 命令行指定 /V:ON 或者在批处理文件中使用 setlocal 来打开这一功能。
修改后的代码运行后的样子:
@echo offsetlocal EnableDelayedExpansionset size=0
set sum=0for /d %%A in (*) do (@for /r %%B in ("%%A\*") do (set /a sum+=1set /a size+=%%~zB)echo %%A 有 !sum! 个文件,共有 !size! 字节set sum=0set size=0
)endlocalC:\Dev>1.bat
db 有 18 个文件,共有 260828 字节
dootask 有 22 个文件,共有 1192147 字节
htdocs 有 3 个文件,共有 1442 字节
ICS 有 32 个文件,共有 146073 字节
nettool 有 9 个文件,共有 117585 字节
python 有 1 个文件,共有 36 字节
route 有 7 个文件,共有 518235 字节
shell-script 有 4 个文件,共有 4805 字节
SMSBoom 有 22 个文件,共有 264316 字节
tcpip 有 1 个文件,共有 10 字节
tyy 有 6 个文件,共有 68862 字节
vue 有 7 个文件,共有 442175 字节
vulhub 有 17 个文件,共有 19310 字节
web 有 23 个文件,共有 18391 字节
能够正确地工作。