【问题标题】:Batch file which counts all folders and subfolders on specific directory统计特定目录中所有文件夹和子文件夹的批处理文件
【发布时间】:2015-02-19 09:51:53
【问题描述】:

我是脚本菜鸟,但我需要批处理文件,它可以从用户那里获取特殊的文件夹方式,并计算该目录中的所有文件夹和子文件夹。我现在有这样的事情:

@echo off
set /a allcount=0
for /f %%a in ('dir /b /s /ad %folder%^|find /c /v "" ') do set count=%%a
echo %count%

但它只计入当前文件夹并打印很多行,例如“文件夹名称太长”。有人可以帮我完成我的剧本吗?

【问题讨论】:

  • folder 变量是如何定义的(我看不到任何定义,set "folder=%~1")?如果未定义,%folder% 结果为空字符串 => dir 当前文件夹

标签: windows batch-file scripting cmd


【解决方案1】:

这列出了文件夹的大小。它来自我在 MS 网站上的磁盘清理文章。

查看文件占用空间的位置

这将列出驱动器上文件夹的文件数量和大小。每个命令都有一个子集,因此您可以更好地管理它。

开始 - 所有程序 - 附件 - 右键单击​​命令提示符并选择以管理员身份运行。键入(或通过右键单击命令提示符窗口并选择粘贴来复制和粘贴)。

然后配置命令提示符。右键单击命令提示符的标题栏 - 属性 - 布局选项卡 - 并为屏幕缓冲区大小高度输入 1000,为窗口大小高度输入 43(或 50)。如果需要,可以更改颜色(颜色选项卡)和字体(字体选项卡)。

查看文档中文件夹的大小,不包括音乐、视频或图片文件夹。

for /f "skip=2 tokens=3" %A in ('Reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "Personal"') do set doc=%A

for /f "usebackq tokens=2* delims= " %i IN (`dir "%doc%" /a /s ^|findstr /i /v "\/"^|findstr /l /v "Pictures Music Video"`) DO @echo %j&echo.

查看音乐中文件夹的大小。

for /f "skip=2 tokens=4" %A in ('Reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Music"') do set Doc=%A

for /f "usebackq tokens=2* delims= " %i IN (`dir "%doc%" /a /s ^|findstr /i /v "\/"`) DO @echo %j&echo.

查看图片中文件夹的大小。

for /f "skip=2 tokens=4" %A in ('Reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Pictures"') do set Doc=%A

for /f "usebackq tokens=2* delims= " %i IN (`dir "%doc%" /a /s ^|findstr /i /v "\/"`) DO @echo %j&echo.

查看视频中文件夹的大小。

for /f "skip=2 tokens=4" %A in ('Reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Video"') do set Doc=%A

for /f "usebackq tokens=2* delims= " %i IN (`dir "%doc%" /a /s ^|findstr /i /v "\/"`) DO @echo %j&echo.

查看桌面上文件夹的大小。

for /f "skip=2 tokens=3" %A in ('Reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "Desktop"') do set doc=%A

for /f "usebackq tokens=2* delims= " %i IN (`dir "%doc%" /a /s ^|findstr /i /v "\/"`) DO @echo %j&echo.

查看Windows文件夹的大小。

for /f "usebackq tokens=2* delims= " %i IN (`dir "%windir%" /a /s ^|findstr /i /v "\/"`) DO @echo %j&echo.

要查看文件夹的大小,请查看 Program Files 文件夹。

for /f "usebackq tokens=2* delims= " %i IN (`dir "%ProgramFiles%" /a /s ^|findstr /i /v "\/"`) DO @echo %j&echo.

要计算行数,这个 vbscript 会做。

Set Arg = WScript.Arguments
set WshShell = createObject("Wscript.Shell")
Set Inp = WScript.Stdin
Set Outp = Wscript.Stdout

        Do Until Inp.AtEndOfStream
            Line=Inp.readline
            outp.writeline Line
            Count = Count +1
        Loop
        outp.writeline Count

使用管道将您要计数的内容计入 vbscript。

YourCommand.exe | cscript //nologo <path to vbscript>\count.vbs 

【讨论】:

    【解决方案2】:

    DIR 命令总是显示错误的子目录数

    这是 DIR 命令的固有行为,因为它始终将 .(当前目录)和 ..(祖先目录)计为它枚举的每个目录的子目录。

    这意味着:

    • 非递归列出(即列出根文件夹中的目录)

    Dir ReportsN+2 目录(其中N = 正确值)

    • 递归列出(即所有目录和子目录)

    Dir Reports3N+2 目录(其中N = 正确值)

    重要提示:在我的示例中,我发现 DIR CMD 存在违反此规则的问题。所以,我建议只使用“计数”方法)

    修复报告的值:

    要么

    A) 自己计算目录。

    B) 从 DIR 中捕获报告的值(例如使用 FOR /F 循环)

    计数是更通用的解决方案(它可以递归或非递归地工作,可能会稍微快一些。)

    REM Recursive = DIR /S /B /A:D "Some path" | FIND /I /C /V ""
    REM Recursive (Ignore Links)= DIR /S /B /A:D-L "Some path" | FIND /I /C /V ""
    REM Non-Recursive = DIR /B /A:D "Some path" | FIND /I /C /V ""
    
    Y:\> DIR /S /B /A:D "C:\Windows\System32\" | FIND /I /C /V ""
    1498
    
    Y:\>DIR /S /B /A:D-L "C:\Windows\System32\" | FIND /I /C /V ""
    1497
    
    Y:\> DIR /B /A:D "C:\Windows\System32\" | FIND /I /C /V ""
    1
    

    但是,您也可以使用数学示例找到正确的值:

    注意:与计数方法相比,显示的结果存在差异,我将在下面对此进行扩展。

    Y:\>FOR /F %A IN ('dir /s /A:D "c:\windows\system32" ^| Find "Dir(s)"') DO @( SET /a ( %~A - 2 ^) / 3 )
    1496
    
    Y:\>FOR /F %A IN ('dir /s /A:D-L "c:\windows\system32" ^| Find "Dir(s)"') DO @( SET /a %~A - 2 )
    1
    

    注意:

    当文件夹、Junction 或 Symlink 配置了阻止任何人遍历此文件夹的权限时——这主要是默认 Windows Junctions 设置的情况,以防止操作系统循环文件结构——DIR 将不计算在内这些都是正确的,我们最终得到 3N-2。

    我已经进行了一些测试,DIR 肯定会为 Junction 文件夹添加一个条目,(不添加两个 ... 文件夹)这是我最初的假设,但是然后它还将总数减少了 2 个。

    似乎这个额外的 2 下降来自 DIR 试图忽略较大目录集上根目录的 ... 文件夹,但我需要验证是否是这种情况,或者是否在无法访问的目录中运行时,DIR CMD 总是加 1 减 4。

    无论如何,使用 Count A:D-L 或 Count A:D 的计数方法仍然与目录或目录和连接的总数(*分别)一致,应该是 go-到方法。

    【讨论】:

      【解决方案3】:

      这也有效

      dir /s c:\windows\system32 | Findstr /c:"Dir(s)"
      

      【讨论】:

      • 这没有给出正确的答案。在只有 1 个子目录的目录中,它给出了答案 5 Dir(s) 1,674,526,121,984 bytes free
      • @DavidPostill DIR 命令因在计算目录时计算“.”(当前目录)和“..”(祖先目录)引用而臭名昭著。当您通过目录进行递归时,此问题会更加复杂。您总是在非递归 DIR CMD 上得到 N+2 文件夹的值,在递归 DIR CMD 上得到 3N+2 值(其中 `N = 要评估的子目录的总数)所以,你有两个选项,使用两个方程式之一根据您是否使用递归来找到实际值,或者您可以将输出更改为 Bare,并直接计算 dirs。
      • @DavidPostill Math 例如。 (递归):FOR /F %A IN ('dir /s /A:D "c:\windows\system32" ^| Find "Dir(s)"') DO @(SET /a ( %~A - 2 ^) / 3 ) 数学例如(非递归)FOR /F %A IN ('dir /A:D "c:\windows\system32" ^| Find "Dir(s)"') DO @( SET /a %~A - 2 ) 通用解决方案例如(计数)dir /S /A:D /B "c:\windows\system32" | Find /V /c ""