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


1

在下面的代码中,我需要将文件夹和子文件夹的路径和大小放入文件中。但是,当循环第二次运行时,路径和大小不会被打印到文件中。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

Answers:


1

问题是cd-您正在size.txt每个目录中创建一个两行文件。尝试

对于...中的%% h('“ dir / s / -c / a   %% q   |查找” bytes“ |查找/ v” free“”')...

并删除cd

顺便说一句,您是否意识到自己正在获得累计总额?例如,如果您的目录结构看起来像

100K
a \ b 200K
\ c 400K

然后你的结果会说

一种
700000
a \ b
200000
a \ c
400000

这是因为第二dir/s选项。如果那是您想要的,那很好。我只是认为这可能是一个疏忽。


谢谢斯科特。我忘了那个“ cd”卡曼德。您的方法稍作改动。我将其包括为“ %% q”,以包括名称中包含空格的文件夹。是的,我只需要累积结果。感谢你的关心。
萨钦(Sachin)2012年

@Sachin:谢谢您提醒我有关报价的信息。我首先是Unix用户,我在shell脚本中反身引用变量,但我一直忘记在DOS中进行操作。嗯,我的意思是Windows命令行。
Scott

1

如果可以管理它,请抓住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;

      设置为该命令输出DirSizeSum属性。$()表示执行括号内的内容并替换为括号内的内容。

      展开它:

      • 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-TableOut-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';"

感谢您的快速提示。它确实解决了许多复杂问题。
萨钦(Sachin)2012年

这个目录“ dir / a:d / s / b”正在从目录路径中删除特殊字符。我需要确切的路径。你能帮我吗?
萨钦2012年

@Sachin那些特殊字符是什么?您能否提供一个影响的示例路径?
鲍勃

原始路径:D:\ Songs \ Audio \ Hindi \ Wake Up S!d,它更改为D:\ Songs \ Audio \ Hindi \ Wake Up Sd
Sachin 2012年

@Sachin此问题不是由于dir命令引起的-您的原始文件会执行相同的操作。问题是因为EnableDelayedExpansioncmd首先,在批处理文件中解析一行以弄清楚应该做什么,然后通常在此时扩展变量(%variablename%)。然后执行该行。EnableDelayedExpansion表示!variablename!在执行时在感叹号()中展开变量。这里发生的是变量%%q在解析时被扩展,然后在执行时cmd被阻塞!
鲍勃
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.