批处理 for 命令爬过的坑之在 Windows 命令行下显示目录大小

批处理 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+=%%~zx
    echo %size% Bytes

修改后运行的样子:

@echo off
set size=0
for /r %%x in (db\*) do set /a size+=%%~zx
   echo %size% Bytes

C:\Dev>2.bat
260828 Bytes

如果你对这段代码比较陌生,可查看原作者的文章给出了详细解释。

一、入坑

先前已然在同事面前一顿高谈,不着手实现一下好像有点说不过去。下面是我的第一次尝试。

代码和运行后的样子:

@echo off

set size=0
set sum=0

for /d %%A in (*) do (
    @for /r %%B in ("%%A\*") do (
        set /a sum+=1
        set /a size+=%%~zB
    )
    echo %%A 有 %sum% 个文件,共有 %size% 字节
    set sum=0
    set 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 off

set size=0
set sum=0

for /d %%A in (*) do (
    @for /r %%B in ("%%A\*") do (
        set /a sum+=1
        set /a size+=%%~zB
    )
    echo %%A 有 %0% 个文件,共有 %0% 字节
    set sum=0
    set size=0
)

由于在 for 循环开始运行之前, 0 值已经替换了,echo 不会看到 sum、size 值的修改,所以输出都是 0,而这根本不是你想要的结果。

有一种方法可以修正这一点:延迟扩展允许你用惊叹号来指定一个环境变量,而不是用百分号。表示只有当 CMD 实际想要执行该命令的时候,才扩展它们。由于 ! 在传统上并不是一个特殊字符,这一功能默认是关闭的。要打开延迟扩展,在 CMD 命令行指定 /V:ON 或者在批处理文件中使用 setlocal 来打开这一功能。

修改后的代码运行后的样子:

@echo off

setlocal EnableDelayedExpansion

set size=0
set sum=0

for /d %%A in (*) do (
    @for /r %%B in ("%%A\*") do (
        set /a sum+=1
        set /a size+=%%~zB
    )
    echo %%A 有 !sum! 个文件,共有 !size! 字节
    set sum=0
    set size=0
)

endlocal

C:\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 字节

能够正确地工作。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值