从Windows命令行获取文件夹大小

190

在Windows中,是否可以使用命令行获取文件夹的大小而不使用任何第三方工具?

我希望获得与在Windows资源管理器中右键单击文件夹→属性时相同的结果。

22个回答

161

有一个 内置的Windows工具 可以做到这一点:

dir /s 'FolderName'

这将打印出许多不必要的信息,但结果将是文件夹的大小,如下所示:

 Total Files Listed:
       12468 File(s)    182,236,556 bytes

如果您需要包含隐藏文件夹,请添加/a


11
如果您不需要整数返回值,这是最优雅的解决方案。注意: '/a' 开关将包括隐藏和系统文件在总大小内。 - Oran D. Lord
2
我猜在打印文件大小时无法使用更有用的单位,比如kB或MB,对吗? - David Ferenczy Rogožan
双引号代替单引号。 - user2924019
1
只有在这里重新排列命令才能正常工作 - dir 'FolderName'/s - jeyko

159

你可以递归地累加大小(以下是批处理文件):

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

然而,这有几个问题,因为cmd仅限于32位有符号整数运算。因此,它将错误地获取超过2 GiB的大小1。此外,它很可能会多次计算符号链接和连接点,因此它最多只是一个上限,而不是真正的大小(但您将遇到任何工具的这个问题)。

另一种选择是PowerShell:

Get-ChildItem -Recurse | Measure-Object -Sum Length

或更短:

ls -r | measure -sum Length

如果你想要更漂亮:

switch((ls -r|measure -sum Length).Sum) {
  {$_ -gt 1GB} {
    '{0:0.0} GiB' -f ($_/1GB)
    break
  }
  {$_ -gt 1MB} {
    '{0:0.0} MiB' -f ($_/1MB)
    break
  }
  {$_ -gt 1KB} {
    '{0:0.0} KiB' -f ($_/1KB)
    break
  }
  default { "$_ bytes" }
}

你可以直接从 cmd 中使用这个命令:

powershell -noprofile -command "ls -r|measure -sum Length"

1我确实有一个未完成的大数库在批处理文件中,它至少正确地实现了任意精度的整数加法。我想我应该把它发布出来。


2
在我看来,PowerShell比Unix更像Unix,因为大多数核心命令确实是正交的。在Unix中,“du”给出目录大小,但它所做的只是遍历树并求和。这可以非常优雅地通过管道表达,就像这里一样 :-)。因此,对于PowerShell,我通常会寻找如何将高级目标分解为合适的低级操作。 - Joey
3
我明白了,这种做法似乎会忽略隐藏文件夹。如果我想要包含隐藏文件夹,就可以使用ls -force -r命令。 - garg
2
“folder*” 对我不起作用,我放置的文件夹大小显示为0字节,有什么解决办法吗? - IT researcher
2
稍微好看一点的版本:powershell -noprofile -command "'{0:N0}' -f (ls -r|measure -s Length).Sum" - zumalifeguard
1
@athos:在批处理文件中使用%1代替folder,或者在PowerShell脚本中添加一个参数,并将其作为参数添加到Get-ChildItem中。但是,如果您在这方面遇到问题(因为它与原始问题无关),也许最好单独提出此类问题。 - Joey
显示剩余11条评论

135

一句话概括:

powershell -command "$fso = new-object -com Scripting.FileSystemObject; gci -Directory | select @{l='Size'; e={$fso.GetFolder($_.FullName).Size}},FullName | sort Size -Descending | ft @{l='Size [MB]'; e={'{0:N2}    ' -f ($_.Size / 1MB)}},FullName"

同样的效果,但是只使用PowerShell:

$fso = new-object -com Scripting.FileSystemObject
gci -Directory `
  | select @{l='Size'; e={$fso.GetFolder($_.FullName).Size}},FullName `
  | sort Size -Descending `
  | ft @{l='Size [MB]'; e={'{0:N2}    ' -f ($_.Size / 1MB)}},FullName

这应该产生以下结果:

Size [MB]  FullName
---------  --------
580,08     C:\my\Tools\mongo
434,65     C:\my\Tools\Cmder
421,64     C:\my\Tools\mingw64
247,10     C:\my\Tools\dotnet-rc4
218,12     C:\my\Tools\ResharperCLT
200,44     C:\my\Tools\git
156,07     C:\my\Tools\dotnet
140,67     C:\my\Tools\vscode
97,33      C:\my\Tools\apache-jmeter-3.1
54,39      C:\my\Tools\mongoadmin
47,89      C:\my\Tools\Python27
35,22      C:\my\Tools\robomongo

2
有没有办法在基本文件夹中显示所有文件和以MB为单位的大小? 在这种情况下 C:\my\Tools\ - Raunak Thomas
2
当文件夹数量过多时,它会崩溃(例如在 C:驱动器中)。 - Raunak Thomas
4
“0.00 C:\Windows”可以优化所有文件夹吗?我已经尝试以管理员身份运行了。 - Tilo
这很好,但它截断了我的组件文件夹名称。有什么命令可以完整显示它们吗? - sean.net
@sean.net 你的意思是长文件夹名字以“...”结尾吗?这就是 ft (Format-Table) 的工作方式。你可以尝试使用 fl (Format-List)。 - frizik

71

我建议从Microsoft提供的此链接下载Sysinternals Suite中的实用程序DU: http://technet.microsoft.com/en-us/sysinternals/bb896651

usage: du [-c] [-l <levels> | -n | -v] [-u] [-q] <directory>
   -c     Print output as CSV.
   -l     Specify subdirectory depth of information (default is all levels).
   -n     Do not recurse.
   -q     Quiet (no banner).
   -u     Count each instance of a hardlinked file.
   -v     Show size (in KB) of intermediate directories.


C:\SysInternals>du -n d:\temp

Du v1.4 - report directory disk usage
Copyright (C) 2005-2011 Mark Russinovich
Sysinternals - www.sysinternals.com

Files:        26
Directories:  14
Size:         28.873.005 bytes
Size on disk: 29.024.256 bytes

顺便看一下其他实用工具吧,它们对每个Windows专业人员都是救命稻草。


19
我猜那几乎不算是“没有使用任何第三方工具”。 - Joey
13
好的,但是它认为家庭不应被视为“第三方”。 - Steve
2
当然,但这仍然需要额外下载(或者使用 \\live.sysinternals.com 如果它仍然存在的话)。我完全同意,所有的 sysinternals 工具都应该默认包含在内。虽然对于许多用途来说,PowerShell 是一个非常值得推荐的替代品。 - Joey
1
有人提到了 Powershell 吗?请尝试以下命令:"{0:N2}" -f ((Get-ChildItem C:\Temp -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB) + " MB" - John Homer
3
我建议你们都下载Mark Russinovich开发的任何工具 :) 每当我找到一款拯救我的工具时,我总是看到这个名字。 - dkellner
此实用程序(v1.61)存在权限问题,导致某些文件的大小未被包括在内。除非使用管理员提升的控制台,否则该工具可能不太可靠。注意:文件和大小会在“dir”命令中列出。(我曾认为这可能是由于问题目录包含许多大于2GB的数据库文件而导致的文件大小问题。) - Disillusioned

22
如果您的计算机上已安装了 Git (变得越来越常见),只需打开 MINGW32 并输入:du folder

8
如果你想要以人类可读的方式显示文件夹大小、仅包括一级子目录并按照大小排序,可以使用以下命令:du -h -d 1 文件夹 | sort -h - vard

11

这里有一段我编写的PowerShell代码,用于列出当前目录下所有文件夹的大小和文件数量。根据您的需要,请随意重新使用或修改。

$FolderList = Get-ChildItem -Directory
foreach ($folder in $FolderList)
{
    set-location $folder.FullName
    $size = Get-ChildItem -Recurse | Measure-Object -Sum Length
    $info = $folder.FullName + "    FileCount: " + $size.Count.ToString() + "   Size: " + [math]::Round(($size.Sum / 1GB),4).ToString() + " GB"
    write-host $info
}

适用于我。如果您在无头服务器上使用,这将非常有用。 - andrew pate
简单而优雅!我的版本:$FolderList = Get-ChildItem -Directory -Force; $data = foreach ($folder in $FolderList) { set-location $folder.FullName; $size = Get-ChildItem -Recurse -Force | Measure-Object -Sum Length; $size | select @{n="路径"; e={$folder.Fullname}}, @{n="文件数"; e={$_.count}}, @{n="大小"; e={$_.Sum}} } 这将提供对象(更符合PowerShell的风格),'FileCount'和'Size'是整数(因此您可以在需要时对它们进行处理),'Size'以字节为单位,但您可以使用 $Data.Size / 1GB 轻松将其转换为GB(或您想要的单位)。 - curropar
一行代码:$Data = dir -Directory -Force | %{ $CurrentPath = $_.FullName; Get-ChildItem $CurrentPath -Recurse -Force -ErrorAction SilentlyContinue | Measure-Object -Sum Length | select @{n="Path"; e={$CurrentPath}}, @{n="FileCount"; e={$_.count}}, @{n="Size"; e={$_.Sum}} } - curropar
我最喜欢这个,但是 set-location 是不是多余的?你可以直接使用 Get-ChildItem $folder.FullName,这样你就可以在不改变当前目录的情况下完成操作。 - BenderBoy
1
谢谢@BenderBoy。最好删除set-location并直接使用Get-ChildItem $folder.FullName - Ryan Lee

10

我建议使用我编写的https://github.com/aleksaan/diskusage实用工具。非常简单和有用。而且速度很快。

只需在命令行中键入

diskusage.exe -path 'd:/go; d:/Books'

并获取按照大小排列的文件夹列表

  1.| DIR: d:/go      | SIZE: 325.72 Mb   | DEPTH: 1 
  2.| DIR: d:/Books   | SIZE:  14.01 Mb   | DEPTH: 1 

此示例在HDD上执行时间为272ms

您可以增加子文件夹的深度以进行分析,例如:

diskusage.exe -path 'd:/go; d:/Books' -depth 2

并且可以获取所选文件夹及其子文件夹的大小

  1.| 目录: d:/go            | 大小: 325.72 Mb   | 深度: 1 
  2.| 目录: d:/go/pkg        | 大小: 212.88 Mb   | 深度: 2 
  3.| 目录: d:/go/src        | 大小:  62.57 Mb   | 深度: 2 
  4.| 目录: d:/go/bin        | 大小:  30.44 Mb   | 深度: 2 
  5.| 目录: d:/Books/Chess   | 大小:  14.01 Mb   | 深度: 2 
  6.| 目录: d:/Books         | 大小:  14.01 Mb   | 深度: 1 
  7.| 目录: d:/go/api        | 大小:   6.41 Mb   | 深度: 2 
  8.| 目录: d:/go/test       | 大小:   5.11 Mb   | 深度: 2 
  9.| 目录: d:/go/doc        | 大小:   4.00 Mb   | 深度: 2 
 10.| 目录: d:/go/misc       | 大小:   3.82 Mb   | 深度: 2 
 11.| 目录: d:/go/lib        | 大小: 358.25 Kb   | 深度: 2 

*** 已扫描服务器上的3.5Tb文件,耗时3m12s ***


请注意,您是作者。 (来自https://stackoverflow.com/help/promotion:“但是,您必须在答案中披露您的关联。”) - aeracode
是的,我是github.com/aleksaan/diskusage程序的作者。 - Alexander Anufriev
版本2.8.0 https://github.com/aleksaan/diskusage 已发布。Duck已经诞生了! - Alexander Anufriev

3

我猜这只能在目录相对静态且其内容在两个dir命令执行之间不改变的情况下才能起作用。也许有一种方法可以将其合并为一个命令以避免这种情况,但对于我的目的来说,这已经足够了(我不需要完整的列表;只需要概述即可)。

GetDirSummary.bat脚本:

@echo off
rem  get total number of lines from dir output
FOR /F "delims=" %%i IN ('dir /S %1 ^| find "asdfasdfasdf" /C /V') DO set lineCount=%%i
rem  dir summary is always last 3 lines; calculate starting line of summary info
set /a summaryStart="lineCount-3"
rem  now output just the last 3 lines
dir /S %1 | more +%summaryStart%

使用方法:

运行 GetDirSummary.bat c:\temp

输出结果:

 Total Files Listed:
          22 File(s)         63,600 bytes
           8 Dir(s)  104,350,330,880 bytes free

这实际上是需要的回复。没有外部工具,也不需要执行PowerShell(这会触发一些警报并且肯定会很慢)。谢谢! - DefToneR

2
这里有一个解决方案,符合您最初的要求,与Win Vista或更高版本兼容,可为文件大小提供易读性,并避免大多数人所经历的文件大小限制。如果安装了Robocopy,则仅适用于XP。只需将文件夹拖放到该批处理文件上,或使用下面提到的更好方法。
@echo off
setlocal enabledelayedexpansion
set "vSearch=Files :"

For %%i in (%*) do (
    set "vSearch=Files :"
    For /l %%M in (1,1,2) do ( 
        for /f "usebackq tokens=3,4 delims= " %%A in (`Robocopy "%%i" "%%i" /E /L /NP /NDL /NFL ^| find "!vSearch!"`) do (
            if /i "%%M"=="1" (
                set "filecount=%%A"
                set "vSearch=Bytes :"
            ) else (
                set "foldersize=%%A%%B"
            )
        )
    )
    echo Folder: %%~nxi FileCount: !filecount! Foldersize: !foldersize!
    REM remove the word "REM" from line below to output to txt file
    REM echo Folder: %%~nxi FileCount: !filecount! Foldersize: !foldersize!>>Folder_FileCountandSize.txt
)
pause

为了方便使用此批处理文件,请将其放置在“发送到”文件夹中。 这样,您就可以右键单击一个文件夹或一组文件夹,选择“发送到”选项,然后选择此批处理文件。
要找到计算机上的“发送到”文件夹,最简单的方法是打开cmd,然后按原样复制此行。
explorer C:\Users\%username%\AppData\Roaming\Microsoft\Windows\SendTo


对于任何担心Robocopy会移动文件的人,不用担心。/l选项只是列出文件列表。此外,Robocopy不是第三方软件,它在Windows中默认安装自Vista版本开始,XP需要手动安装。 - julesverne
感谢您的补充。很高兴看到这个主题仍然吸引着大家的关注 ;-) 可能需要添加如何安装robocopy(非常好用的工具!)。 - Eldad Assis
我在4年前在 stackoverflow 上发布了原始解决方案。到目前为止,使用 robocopy 是最快的解决方案。 - user1016274
非常感谢您提供了“发送到文件夹”的设置。我使用Windows已经有35年了,一直想知道“发送到”有什么用,以及如何使用它。您的示例终于给了我启发。非常酷!非常感谢! - undefined

2

这段代码已经经过测试。您可以再次检查它。

@ECHO OFF
CLS
SETLOCAL
::Get a number of lines contain "File(s)" to a mytmp file in TEMP location.
DIR /S /-C | FIND "bytes" | FIND /V "free" | FIND /C "File(s)" >%TEMP%\mytmp
SET /P nline=<%TEMP%\mytmp
SET nline=[%nline%]
::-------------------------------------
DIR /S /-C | FIND "bytes" | FIND /V "free" | FIND /N "File(s)" | FIND "%nline%" >%TEMP%\mytmp1
SET /P mainline=<%TEMP%\mytmp1
CALL SET size=%mainline:~29,15%
ECHO %size%
ENDLOCAL
PAUSE

谢谢,对于小于1GB的文件夹它对我有效,但是例如,我有一个3,976,317,115字节(3.70GB)的文件夹,脚本返回给我这个字符串“) 932”,你知道为什么吗? - elady
@elady:请查看2012年10月10日最受欢迎的答案,时间为7:16,由于32位限制。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接