无法在 Windows 命令行中输出到文件

无法在 Windows 命令行中输出到文件

在下面的代码中,我需要将文件夹和子文件夹的路径和大小放入文件中。但是当循环第二次运行时,路径和大小不会打印到文件中。size.txt 仅包含第一个文件夹的路径和大小。请有人帮帮我。

@echo off

SETLOCAL EnableDelayedExpansion
SET xsummary=
SET xsize=

for /f "tokens=1,2 delims=C" %%i IN ('"dir /s /-c /a | find "Directory""') do (echo    C%%j >> abcd.txt)
for /f "tokens=*" %%q IN (abcd.txt) do (
cd "%%q"
For /F "tokens=*" %%h IN ('"dir /s /-c /a | 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.%%q >> size.txt
echo.!xsize! >> size.txt

答案1

问题是— 你在每个目录中都cd创建了一个两行文件。尝试size.txt

对于...%%h在('“dir /s /-c /a  %%q  | 查找“字节”| 查找/v“免费””')...

并删除cd

顺便问一下,您是否意识到您正在获得累计总数?例如,如果您的目录结构如下所示

10万
200K 元
400K

那么你的结果会说

A
700000
\b
200000
\c
400000

这是因为第二个dir/s选项。如果这是你想要的,那就没问题;我只是认为这可能是一个疏忽。

答案2

如果你能做到,可以抓住Sysinternals 杜utility 和 running 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。这也会摆脱临时文件。


修改后的版本可处理名称中带有感叹号的文件夹。使用 Scott 的答案。请参阅下面的评论。

请注意,这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.txtFormat-TableOut-String位是为了防止截断到控制台窗口宽度(通常为 80 个字符)。 考虑到 Windows 路径通常限制为 255 个字符(IIRC),4096 应该足以容纳任何 Windows 路径和目录大小的字符。 justAutoSize意味着尽可能缩短而不截断,而不是用大量空格填充以适应 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';"

相关内容