Board logo

标题: [文件操作] [已解决]批处理如何生成树状目录带文件大小? [打印本页]

作者: DoubleU    时间: 2019-12-16 11:55     标题: [已解决]批处理如何生成树状目录带文件大小?

本帖最后由 DoubleU 于 2019-12-16 17:45 编辑

各位大神好,小弟不是开发人员,平时也没有研究过,很多时候只是简单了解用过批处理,之前用的批处理都比较简单,百度一般都能解决个人需求,这次的需求稍微复杂了一些,从上周末开始搜索测试了蛮久,均未能完美解决,所以在此求助大神抽空帮忙指点一下,先行谢过了。
我的需求是:文件名、大小(mb的显示mb,gb的显示gb)
需求说明:
本地文件夹中有很多子文件夹及文件,想要做清理,需要现有一份清单列表,所以想通过批处理来输出一份文本,最好是树状结构,内容包含文件名称及大小,开始直接用tree /f >>1.txt 可以得到想要的结果,在整理过程中发现,很多时候需要对比文件大小,并不能完全满足需求;
于是开始百度和在论坛中搜寻,目前找了2段代码相对比较贴近,
来自百度的源代码1:优点:有名称、时间、路径、大小。缺点:不能输出为txt、文件大小为字节数,无法换算为MB  GB,  这个是比较接近需求的一段代码了。
  1. ' 2>nul 3>nul&cls&@echo off
  2. '&rem 批处理/bat生成能显示文件大小的树状/树形目录结构
  3. '&mode con lines=3000
  4. '&set #=Any question&set @=WX/&set $=Q&set/az=0x53b7e0b4
  5. '&title %#% +%@%%$%%$% %z%
  6. '&cd /d "%root%"
  7. '&cscript -nologo -e:vbscript "%~f0" "."
  8. '&echo;%#% +%@%%$%%$% %z%
  9. '&pause&exit
  10.   
  11. Set fso = CreateObject("Scripting.FileSystemObject")
  12. Set TreePath = fso.GetFolder(WSH.Arguments(0))
  13. currentpath = fso.GetFile(WSH.ScriptFullName).ParentFolder.Path
  14. OutFile = currentpath & "\#OutTree.txt"
  15. fs = 0
  16. For Each f In TreePath.Files
  17.     fs = fs+f.size
  18. Next
  19. TreeStr = TreePath.path & " [" & TreePath.Size & " 字节]" & vbCrLf
  20. Tree TreePath.path,""
  21. WSH.echo TreeStr
  22. WSH.Quit
  23.   
  24. Sub Tree(Path,SFSpace)
  25.     Dim i,TempStr,FlSpace,fsize
  26.     FlSpace = SFSpace & "  "
  27.     Set CrntFolder = fso.GetFolder(Path)
  28.     i = 0:TempStr = "├─"
  29.     For Each ConFile In CrntFolder.Files
  30.         If ConFile.Path <> WSH.ScriptFullName Then
  31.             i = i + 1
  32.             If i = CrntFolder.Files.Count And CrntFolder.SubFolders.Count = 0 Then TempStr = "└─"
  33.             TreeStr = TreeStr & FlSpace & Tempstr & ConFile.name & " [" & ConFile.size & " 字节]" & vbCrLf
  34.         End If
  35.     Next
  36.     i = 0:TempStr = "├─"
  37.     For Each SubFolder In CrntFolder.SubFolders
  38.         fsize = 0:i = i + 1
  39.         If i = CrntFolder.SubFolders.Count Then
  40.             TempStr = "└─"
  41.             SFSpace = FlSpace & "  "
  42.         Else
  43.             SFSpace = FlSpace & "│"
  44.         End If
  45.         For Each f In SubFolder.Files
  46.             If f.Path <> WSH.ScriptFullName Then
  47.                 fsize = fsize+f.size
  48.             End If
  49.         Next  
  50.         TreeStr = TreeStr & FlSpace & TempStr & SubFolder.name & " [" & SubFolder.size & " 字节]" & vbCrLf
  51.         Tree SubFolder,(SFSpace)
  52.     Next
  53. End Sub
复制代码
来自论坛中搜索到的源代码2:优点:大小可以换算为MB,GB。缺点:1.不是树状结构,开起来费劲;2.输出结果是在C盘用户下;3.需要用WindowsPowerShell运行。
  1. $Lists = New-Object System.Text.StringBuilder;
  2. $files = ls 'D:\1\' -r | ?{$_.Directory};
  3. $m = $files.Count.tostring().Length;
  4. Foreach ( $i in $files )
  5. {
  6. $index++;
  7. $ref = $i.Length;
  8. switch ( $ref.tostring().length )
  9. {
  10. {$_ -le 3} { $length = "{0:0.000} Byte" -f ($ref);break}
  11. {$_ -le 6} { $length = "{0:0.000} KB" -f ($ref/1KB);break}
  12. {$_ -le 9} { $length = "{0:0.000} MB" -f ($ref/1MB);break}
  13. $_ { $length = "{0:0.000} GB" -f ($ref/1GB)}
  14. }
  15. $n = '[' + $index.tostring().padleft($m,' ') + ']';
  16. [void]$Lists.AppendLine($n+' '+$i.name);
  17. [void]$Lists.AppendLine(' '*($m+3)+$length);
  18. [void]$Lists.AppendLine(' '*($m+3)+$i.LastWriteTime);
  19. [void]$Lists.AppendLine(' '*($m+3)+$i.FullName);
  20. [void]$Lists.AppendLine('');
  21. }
  22. [IO.File]::WriteAllLines("$pwd\输出.log",$Lists,[text.encoding]::Default);
复制代码
这两段代码都是我目前找到的相对比较符合需求的代码,但是都无法完美解决问题,求大神帮忙看下,尽量在代码1的基础上能帮忙调整下,能增加:1.输出txt结果到当前目录;2.树状机构输出;3.大小可以换算为MB,GB。
作者: Batcher    时间: 2019-12-16 12:35

回复 1# DoubleU


代码2的最后一行:
[IO.File]::WriteAllLines("$pwd\输出.log",$Lists,[text.encoding]:efault);
红色字体改成你希望的路径,试试能否解决这个问题【2.输出结果是在C盘用户下】
作者: DoubleU    时间: 2019-12-16 14:17

回复 2# Batcher
嗯嗯 可以了 我修改了标红的部分,可以正常输出到指定目录了,感谢大大。
作者: a20150604    时间: 2019-12-16 15:49

回复 1# DoubleU

我没有完全按你的需求写, 实际是 vbs, 但保存了 bat 直接运行, 结果输出在命令行, 你自己动手加入输出文件, 文件 size 做简单的单位换算处理就能达到你的需求了
  1. Rem^ & @echo off & mode 300,9999
  2. Rem^ &cscript //NoLogo //E:VBScript "%~f0"
  3. Rem^ &pause
  4. Rem^ &goto :eof
  5. Public fso, input_file, output_file
  6. Public layer
  7. Public Branch
  8. call main
  9. Sub main()
  10.     ReDim Branch(1000)
  11.     layer = 0
  12.     Set fso = CreateObject("Scripting.FileSystemObject")
  13.     ' 脚本对象 和 当前目录
  14.     Set obj_wsc_shell = CreateObject("wscript.shell")
  15.     HostFolder = obj_wsc_shell.CurrentDirectory & "\"
  16.     ' HostFolder = ThisWorkbook.Path & "\"
  17.     Call DoFolder(fso.GetFolder(HostFolder))
  18.     wscript.Quit
  19. End Sub
  20. Sub DoFolder(Folder)
  21.     Dim i
  22.     pref_str = ""
  23.     For i = 1 To layer - 1
  24.         pref_str = pref_str & Branch(i)
  25.     Next
  26.     If layer > 0 Then
  27.         If Branch(layer) = "   " Then
  28.             pref_str = pref_str & "  └─"
  29.         Else
  30.             pref_str = pref_str & "  ├─"
  31.         End If
  32.     End If
  33.     wscript.echo  pref_str & Folder.Name
  34.     ' Debug.Print pref_str & Folder.Name
  35.     ' 在子目录中递归调用
  36.     Dim SubFolder
  37.     Dim count_SubFolders, cnt_SubFolder_or_file
  38.     count_SubFolders = Folder.SubFolders.Count
  39.     count_files = Folder.Files.Count
  40.     count_SubFolders_and_files = count_SubFolders + count_files
  41.     cnt_SubFolder_or_file = 0
  42.     For Each SubFolder In Folder.SubFolders
  43.         cnt_SubFolder_or_file = cnt_SubFolder_or_file + 1
  44.         layer = layer + 1
  45.         ' Branch 用于子对象
  46.         If (cnt_SubFolder_or_file >= count_SubFolders_and_files) Then
  47.             Branch(layer) = "   "
  48.         Else
  49.             Branch(layer) = "  │"
  50.         End If
  51.         Call DoFolder(SubFolder)
  52.         layer = layer - 1
  53.     Next
  54.     Dim file
  55.     For Each file In Folder.Files
  56.         cnt_SubFolder_or_file = cnt_SubFolder_or_file + 1
  57.         layer = layer + 1
  58.         If (cnt_SubFolder_or_file >= count_SubFolders_and_files) Then
  59.             Branch(layer) = "   "
  60.         Else
  61.             Branch(layer) = "  │"
  62.         End If
  63.         Call doFile(file)
  64.         layer = layer - 1
  65.     Next
  66. End Sub
  67. Sub doFile(ByRef input_file)
  68.     Dim i
  69.     pref_str = ""
  70.     For i = 1 To layer - 1
  71.         pref_str = pref_str & Branch(i)
  72.     Next
  73.     If layer > 0 Then
  74.         If Branch(layer) = "   " Then
  75.             pref_str = pref_str & "  └─"
  76.         Else
  77.             pref_str = pref_str & "  ├─"
  78.         End If
  79.     End If
  80.     wscript.echo  pref_str & input_file.Name & " : " & input_file.Size & " Bytes"
  81. End Sub
复制代码

作者: DoubleU    时间: 2019-12-16 17:44

回复  DoubleU

我没有完全按你的需求写, 实际是 vbs, 但保存了 bat 直接运行, 结果输出在命令行, 你自己 ...
a20150604 发表于 2019-12-16 15:49


厉害了  大大这个可以正常跑了,太感谢了。
作者: DoubleU    时间: 2019-12-16 17:51

回复  DoubleU

我没有完全按你的需求写, 实际是 vbs, 但保存了 bat 直接运行, 结果输出在命令行, 你自己 ...
a20150604 发表于 2019-12-16 15:49



    对于一个有点强迫证的人来说,完美解决真的是太舒心,再次感谢大大的帮忙,不甚感谢。
作者: Ares777    时间: 2020-12-11 18:19

回复 6# DoubleU


    请问,在第三个回答得基础上,可以指导一下文件大小转换的代码怎么写吗 (比如转换成Mb),谢谢啦
作者: Ares777    时间: 2020-12-11 18:21

回复 4# a20150604


    大佬,我想请教一下,在你这个回答中 文件大小转换的代码怎么写啊 (比如转换成Mb),麻烦啦
作者: newswan    时间: 2020-12-14 14:22

linux命令 tree.exe 可以输出目录树,带 文件大小
作者: 2319375211    时间: 2020-12-29 06:26

本帖最后由 2319375211 于 2021-1-3 10:07 编辑

回复 8# Ares777
  1. If Round(input_file.size/1099511627776, 3) > 1 Then
  2.       wscript.echo  pref_str & input_file.Name & "  [" & Round(input_file.size/1099511627776, 3) & " TB]"
  3. ElseIf Round(input_file.size/1073741824, 3) > 1 Then
  4.       wscript.echo  pref_str & input_file.Name & "  [" & Round(input_file.size/1073741824, 2) & " GB]"
  5. ElseIf Round(input_file.size/1048576, 3) > 1 Then
  6.       wscript.echo  pref_str & input_file.Name & "  [" & Round(input_file.size/1048576, 1) & " MB]"
  7. ElseIf Round(input_file.size/1024, 3) > 1 Then
  8.       wscript.echo  pref_str & input_file.Name & "  [" & Round(input_file.size/1024, 1) & " KB]"
  9. Else
  10.       wscript.echo  pref_str & input_file.Name & "  [" & input_file.Size & " Byte]"
  11. End If
复制代码

作者: Ares777    时间: 2021-1-6 19:47

回复 10# 2319375211


    非常感谢!




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2