如果可以管理它,请抓住Sysinternals du实用程序并运行,以免造成混乱du -v <directoryname>。输出将为千字节。该-v选项意味着输出所有子目录的大小。
使用您当前的脚本,问题似乎出在循环中时附加文本。一个简单的解决方法是将输出到命令提示符窗口,如下所示:
echo %%q
echo !xsize!
运行批处理文件时,将其输出发送到文本文件: test.bat > size.txt
快速提示:可以使用以下方法简化第一位:
for /f "tokens=*" %%q in ('dir /a:d /s /b') do (
cd "%%q"
...
echo !xsize!
)
基本上,它取代了使用find与/a:d选项(只列出目录)和/b(使用空格式,没有标题或摘要)。这也摆脱了临时文件。
修改后的版本可用于名称中带有感叹号的文件夹。使用斯科特的答案。请参阅下面的评论。
请注意,REM这是一条评论。
@echo off
REM clear the file
type NUL > size.txt
for /f "tokens=*" %%q IN ('dir /a:d /s /b') do (
echo %%q >> size.txt
REM Run :getsize, passing "%%q" including quotes as the first parameter
call :getsize "%%q" >> size.txt
)
REM go to the end of the file, i.e. exit
goto :eof
:getsize
REM %1 is the first parameter. It should already be quoted.
for /f "tokens=*" %%h IN ('"dir /s /-c /a %1 | find "bytes" | find /v "free""') do set xsummary=%%h
for /f "tokens=1,2 delims=)" %%a in ("%xsummary%") do set xsize=%%b
set xsize=%xsize:bytes=%
set xsize=%xsize: =%
echo %xsize%
goto :eof
一种替代方法是使用PowerShell:
Get-ChildItem -Recurse | ?{ $_.PSIsContainer } | %{$_ | Add-Member -MemberType NoteProperty -Name DirSize -Value 0; $_.DirSize = $(Get-ChildItem -Recurse $_.Fullname | ?{ -not $_.PSIsContainer } | Measure-Object -Sum -Property Length).Sum; $_} | Sort-Object DirSize -Descending | Select-Object -First 10 FullName,DirSize | Format-Table -AutoSize | Out-String -Width 4096 | Out-File 'sizes.txt';
为了尽可能完整,这太过复杂了-而且,这些命令大多数都具有较短的别名。这只是更具可读性。而且,如果将某些部分分成函数/它们自己的行,那么它将变得更易读,甚至更短。
展开它:
Get-ChildItem -Recurse
递归列出所有子目录和文件
?{ $_.PSIsContainer }
筛选,以便仅保留目录(?是的别名Where-Object)。$_指的是通过管道Get-ChildItem传递给该对象的对象-由于传递了对象的列表/数组,因此会一次处理一个对象。
%{$_ | Add-Member -MemberType NoteProperty -Name DirSize -Value 0; $_.DirSize = $(Get-ChildItem -Recurse $_.Fullname | ?{ -not $_.PSIsContainer } | Measure-Object -Sum -Property Length).Sum; $_}
计算每个目录的大小(%是的别名Foreach-Object,因此请{ }在每个单独的对象上运行它们之间的内容。按照前面的部分,每个对象都是一个目录。)
展开它:
$_ | Add-Member -MemberType NoteProperty -Name DirSize -Value 0;
;与管道(|)相反,分号()表示行/语句的结尾,并且不传递输出。该特定位没有输出,它只是将DirSize属性添加到目录对象中并将其初始化为0。这样做是为了更轻松地过滤和稍后整理输出。
$_.DirSize = $(Get-ChildItem -Recurse $_.Fullname | ?{ -not $_.PSIsContainer } | Measure-Object -Sum -Property Length).Sum;
设置为该命令输出DirSize的Sum属性。$()表示执行括号内的内容并替换为括号内的内容。
展开它:
Get-ChildItem -Recurse $_.Fullname
获取当前目录对象的所有内容($_,Fullname仅表示完整路径)。-Recurse意味着也要计算子目录的内容。
?{ -not $_.PSIsContainer }
筛选,以便仅保留文件。目录的Length属性为0,因此我们需要对文件进行总和-本质上是批处理脚本的工作,除了我们要处理实际的数字,对象和属性,而不是使用来获取“数字”作为文本find。
Measure-Object -Sum -Property Length
计算Length传递给它的所有属性的总和。这会返回一个包含属性的对象,该属性Sum用于(.Sum)以上
$_
本质上,echo将对象传递给下一部分。现在它有一个DirSize属性。
Sort-Object DirSize -Descending
降序排列 DirSize
Select-Object -First 10 FullName,DirSize
仅输出前10个,仅输出名称和大小
Format-Table -AutoSize | Out-String -Width 4096 | Out-File 'sizes.txt';
输出到sizes.txt。的Format-Table和Out-String位,以防止截断到控制台窗口宽度(通常80个字符)。考虑到Windows路径通常限制为255个字符(IIRC),对于任何Windows路径和目录大小,4096个字符应该绰绰有余。该AutoSize只是意味着让尽可能短,但不截断,而不是填充有一大堆的空白,以适应4096个字符。
并将命令作为一个衬板运行cmd.exe(您可以在PowerShell中运行以上版本):
powershell -c "Get-ChildItem -Recurse | ?{ $_.PSIsContainer } | %{$_ | Add-Member -MemberType NoteProperty -Name DirSize -Value 0; $_.DirSize = $(Get-ChildItem -Recurse $_.Fullname | ?{ -not $_.PSIsContainer } | Measure-Object -Sum -Property Length).Sum; $_} | Sort-Object DirSize -Descending | Select-Object -First 10 FullName,DirSize | Format-Table -AutoSize | Out-String -Width 4096 | Out-File 'sizes.txt';"