Board logo

标题: [文件操作] 批处理统计文件夹内的图片视频,计算大小时如何统计单位为G [打印本页]

作者: walkercolin    时间: 2024-8-7 16:13     标题: 批处理统计文件夹内的图片视频,计算大小时如何统计单位为G

  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /d %%a in (*) do (
  4.     set/a p=v=z=0
  5.     pushd "%%a"
  6.     for %%b in (*.jpg *.png *.bmp) do (
  7.         rem 计算放在这里,就是对所有图片大小的计算
  8.         set/a z+=%%~zb
  9.         if not "%%~nb"=="000" if not "%%~nb"=="00.1" if not "%%~nb"=="00.2" if not "%%~nb"=="00.3" (
  10.             set/a p+=1
  11.         )
  12.     )
  13.     for %%c in (*.mp4 *.avi *.mov *.mkv) do (
  14.         set/a v+=1,z+=%%~zc
  15.     )
  16.     set/a "sizeMB=z>>20"
  17.     set "sizeUnit=M"
  18.     if !sizeMB! geq 1024 (
  19.         set/a "sizeGB=sizeMB>>10"
  20.         set "sizeUnit=G"
  21.     )
  22.     popd
  23.     if !v! equ 0 (
  24.         rem 没有视频,只有图像
  25.         if "!sizeUnit!"=="G" (
  26.             ren "%%a" "%%a [!p!P-!sizeGB!!sizeUnit!]"
  27.         ) else (
  28.             ren "%%a" "%%a [!p!P-!sizeMB!!sizeUnit!]"
  29.         )
  30.     ) else if !p! equ 0 (
  31.         rem 没有图像,只有视频
  32.         if "!sizeUnit!"=="G" (
  33.             ren "%%a" "%%a [!v!V-!sizeGB!!sizeUnit!]"
  34.         ) else (
  35.             ren "%%a" "%%a [!v!V-!sizeMB!!sizeUnit!]"
  36.         )
  37.     ) else (
  38.         rem 既有图像又有视频
  39.         if "!sizeUnit!"=="G" (
  40.             ren "%%a" "%%a [!p!P!v!V-!sizeGB!!sizeUnit!]"
  41.         ) else (
  42.             ren "%%a" "%%a [!p!P!v!V-!sizeMB!!sizeUnit!]"
  43.         )
  44.     )
  45. )
  46. pause
复制代码
在这段代码中,脚本会统计当前文件夹下每一个子文件夹中的图像和视频的数量以及总大小,并将结果写在文件夹名称的后面,基本符合我的需求,但是早些时候统计文件夹大小时有时候大小会超过一个G,最后计算大小时单位他仍写成M,我使用了chatgpt,希望在统计大小时如果文件夹的内容超过一个G那么就以G为单位,但不知是我表述的有问题还是怎么样,这段代码里当文件内容超过一个计时它就记为1G,但是无论多大都记为1G,我希望能修改成超过1G时单位记为G,有多大就记为多大,比方说如果是1.46G就记为1.46G,不知道是否可行拜托各位大佬了
作者: aloha20200628    时间: 2024-8-7 20:40

本帖最后由 aloha20200628 于 2024-8-7 20:52 编辑

回复 1# walkercolin

以下代码存为 test.bat 置于图片和视频文件所在目录下运行...
批处只能处理不超过2GB的文件尺寸值,超出此限须调用外部计算方法解决,以下代码调用powershell方法(仅因其句式简捷)
运行结果会对每个目标目录更名,其更名格式》“原目录名 [xxxPyyyV-zzzMB]” 或 “原目录名 [xxxPyyyV-zzzGB]”,其中 xxx 或 yyy 可能=0(对应图片或视频文件数量=0)
  1. @echo off &setlocal enabledelayedexpansion &for /d %%d in (*) do (
  2. pushd "%%d" &set/a "np=0,zp=0,nv=0,zv=0"
  3. for /f "tokens=1-2 delims=个文件 " %%a in (
  4. '2^>nul dir /a-d/-c *.jpg *.png *.bmp^|find " 个文件 " ') do (set "np=%%a"&set "zp=%%b")
  5. for /f "tokens=1-2 delims=个文件 " %%a in (
  6. '2^>nul dir /a-d/-c *.mp4 *.avi *.mov *.mkv^|find " 个文件 " ') do (set "nv=%%a"&set "zv=%%b")
  7. for /f %%v in (
  8. ' powershell "if((!zp!+!zv!) -lt 1gb){[math]::round(-(!zp!+!zv!)/1mb,2)}else{[math]::round((!zp!+!zv!)/1gb,2)}" ') do set "zpv=%%v"
  9. if "!zpv:~0,1!"=="-" (set "zpv=!zpv:~1!MB") else (set "zpv=!zpv!GB")
  10. popd & ren "%%~fd" "%%d [!np!P!nv!V-!zpv!]"
  11. )
  12. endlocal&pause&exit/b
复制代码

作者: 77七    时间: 2024-8-8 01:01

本帖最后由 77七 于 2024-8-8 01:10 编辑

批处理统计文件夹内图片、视频数量及大小,并重命名文件夹
  1. @echo off
  2. rem 保存为ansi编码
  3. cd /d "%~dp0"
  4. rem 排除特定文件(000,00.1,00.2,00.3),不需要可以删除下一行
  5. set "_f=^|findstr /rvix /c:"00\.[123]\.[jpb][pnm][gp]" /c:"000\.[jpb][pnm][gp]""
  6. (for /f "delims=" %%d in ('dir /b /ad') do (
  7. setlocal
  8. pushd "%%d"
  9. for /f %%a in ('dir /b /a-d *.jpg *.png *.bmp %_f% ^|find /c /v ""') do (
  10. set /a "1/%%a" && set P=%%aP
  11. )
  12. for /f %%a in ('dir /b /a-d *.mp4 *.avi *.mov *.mkv ^|find /c /v ""') do (
  13. set /a "1/%%a" && set V=%%aV
  14. )
  15. for /f "tokens=3" %%i in ('dir /-c /a-d *.jpg *.png *.bmp *.mp4 *.avi *.mov *.mkv ^|findstr /iec:" 字节"') do (
  16. for /f "tokens=1-2 delims=." %%a in ('powershell -c "$input = %%i; [math]::Round($input / (1024 * 1024 *1024), 2)"') do (
  17. set /a "1/%%a" && set "Z=%%a.%%bG" || for /f "delims=." %%c in ('powershell -c "%%i/1024/1024"') do set Z=%%cM
  18. )
  19. )
  20. popd
  21. if defined Z (
  22. call echo ren "%%d" "%%d [%%p%%%%V%%-%%Z%%]"
  23. )
  24. endlocal
  25. )) 2>nul
  26. pause
复制代码

作者: walkercolin    时间: 2024-8-8 07:01

回复 2# aloha20200628
输出结果为[0P0V-0GB]
作者: walkercolin    时间: 2024-8-8 07:01

回复 3# 77七
输出结果为[0P0V-0GB]
作者: aloha20200628    时间: 2024-8-8 09:18

本帖最后由 aloha20200628 于 2024-8-8 10:28 编辑

回复 4# walkercolin

更正》2楼批处代码应置于 ‘图片+视频子目录’ 的上一级目录中运行,如同一楼代码的运行位置
模拟一楼题型的文件及目录,用2楼代码已测试通过...

作者: 77七    时间: 2024-8-8 10:15

回复 5# walkercolin





0P0V0G这三个0在任何情况下都是不可能出现的
作者: ppll2030    时间: 2024-8-8 16:24

本帖最后由 ppll2030 于 2024-8-8 16:28 编辑

回复 1# walkercolin


    用set /a 的结果都是整数,而另一个问题,bat计算有2GB的限制,综合两点,你的计算方法需要换一个。
试试:把16行的  set/a "sizeMB=z>>20"  替换为:
  1. for /f %%v in ('powershell "[math]::Round(!z! / (1073*1000), 2)"') do set "sizeMB=%%v"
复制代码
把19行的   set/a "sizeGB=sizeMB>>10"  替换为:
  1. for /f %%v in ('powershell "[math]::Round(!z! / (1073*1000*1000), 2)"') do set "sizeGB=%%v"
复制代码

作者: walkercolin    时间: 2024-8-8 18:04

回复 8# ppll2030
有用的,但是这样一来,那些没达到1G的文件夹也仍然按照G的单位进行计算,我希望没超过1G的按M单位,超过的按G单位是否可行呢
作者: ppll2030    时间: 2024-8-8 18:13

本帖最后由 ppll2030 于 2024-8-8 18:34 编辑

回复 9# walkercolin


    你原来的代码是否能正常判断显示MB或GB?因为我没细看,我只是提供了计算方式的修改。
如果if的判断有误,那就还要修改,不如直接用楼上大佬的完整代码了

看了一下,if判断数值,不能有小数点。否则也会报错。
把16行的  set/a "sizeMB=z>>20"  替换为:
  1. for /f %%v in ('powershell "[math]::Round(!z! / (1073*1000), 0)"') do set "sizeMB=%%v"
复制代码
保留整数,方便你的IF做判断。
19行,正常替换,保留两位小数。
这样应该没有问题了。
作者: aloha20200628    时间: 2024-8-8 19:07

本帖最后由 aloha20200628 于 2024-8-8 19:14 编辑

回复 1# walkercolin

      一楼代码中第8,14,16行,一旦文件尺寸值(字节单位)或累加值(字节单位)超过32位整数限就会失误,此乃为何要调用外部计算方法并重写代码的原因
      重写代码不仅是简单重复调用外部计算方法(尤其是在最内层循环体内复用其效率会明显降低),还要兼顾代码的效率,从dir简报中直接获取目标文件总数及其文件尺寸累加值,应该是一条捷径...

作者: walkercolin    时间: 2024-8-8 21:32

回复 10# ppll2030
完美了,感谢大佬帮助愚钝完全不懂什么代码的我拨云见雾,您简直就是当代丹尼斯·里奇,再次感谢您
作者: ppll2030    时间: 2024-8-8 22:02

回复 12# walkercolin


    嗯。楼上的大佬提醒了。你的前半段统计体积,还是用的set/a,所以2GB的限制还是存在的,建议更换dir来获取
作者: 77七    时间: 2024-8-9 18:19

只用bat,适合粗略统计。数值不准确,也无需保留小数点后两位了
  1. @echo off
  2. rem 保存为ansi编码
  3. cd /d "%~dp0"
  4. for %%a in ("000" "00.1" "00.2" "00.3") do (
  5. set _"%%~a"=1
  6. )
  7. set -=-
  8. for /f "delims=" %%d in ('dir /b /ad') do (
  9. set f=%%d
  10. setlocal enabledelayedexpansion
  11. pushd "!f!"
  12. for %%i in (*.jpg *.png *.bmp) do (
  13. if not defined _"%%~ni" (
  14. set /a p+=1
  15. )
  16. set /a m=%%~zi/1024,n+=m
  17. )
  18. set n/=1024
  19. for %%i in (*.mp4 *.avi *.mov *.mkv) do (
  20. set /a v+=1
  21. set t=%%~zi
  22. set t=!t:~0,-3!
  23. if "!t!" neq "" (
  24. set /a n+=!t!/1024
  25. )
  26. )
  27. popd
  28. for %%a in (P V) do (
  29. if defined %%a (
  30. set str=!str!!%%a!%%a
  31. )
  32. )
  33. if !n! gtr 1024 (
  34. set /a x=n/1024
  35. echo ren "!f!" "!f![!str!-!x!G]"
  36. ) else if !n! neq 0 (
  37. echo ren "!f!" "!f![!str!-!n!M]"
  38. )
  39. endlocal
  40. )
  41. pause
复制代码

作者: WHY    时间: 2024-8-10 14:23

本帖最后由 WHY 于 2024-8-14 11:50 编辑

Test.ps1
  1. $srcFolder = 'E:\Test\';                  #源目录路径
  2. $ext1 = @{'.jpg'=1; '.bmp'=1; '.png'=1; '.tif'=1; '.jpeg'=1} #图片扩展名
  3. $name = @{'000'=1; '00.1'=1; '00.2'=1; '00.3'=1}             #需要排除的图片名称
  4. $ext2 = @{'.mp4'=1; '.avi'=1; '.mov'=1; '.mkv'=1}            #视频扩展名
  5. $Hash = @{}
  6. Function Get-Size($sz) {
  7.     If ($sz -ge 1GB) {
  8.         return ($sz/1GB).ToString('0.00G');
  9.     } ElseIf ($sz -ge 1MB) {
  10.         return ($sz/1MB).ToString('0.00M');
  11.     } Else {
  12.         return ($sz/1KB).ToString('0.00K');
  13.     }
  14. }
  15. forEach ($f In (Get-ChildItem -Literal $srcFolder -Recurse -File -Filter *.*)) {
  16.     $fd = $f.DirectoryName;                       #目录名
  17.     If ($ext1.Contains($f.Extension) -and !$name.Contains($f.BaseName)) {
  18.         If (!$Hash.Contains($fd)) {
  19.             $Hash.Add($fd, @(1, 0, $f.Length));   #添加哈希表,键=目录名;值=数组
  20.         } Else {
  21.             $Hash[$fd][0] += 1;                   #图片个数
  22.             $Hash[$fd][2] += $f.Length;           #文件大小
  23.         }
  24.     } ElseIf ($ext2.Contains($f.Extension)) {
  25.         If (!$Hash.Contains($fd)) {
  26.             $Hash.Add($fd, @(0, 1, $f.Length));   #添加哈希表,键=目录名;值=数组
  27.         } Else {
  28.             $Hash[$fd][1] += 1;                   #视频个数
  29.             $Hash[$fd][2] += $f.Length;           #文件大小
  30.         }
  31.     }
  32. }
  33. $keys = $Hash.GetEnumerator().Name;
  34. [Array]::Sort($keys);                             #排序,避免重命名失败
  35. for ($i=$keys.Count-1; $i -ge 0; $i--) {
  36.     $k = $keys[$i];
  37.     $sufFix = '[' + $Hash[$k][0] + 'P' + $Hash[$k][1] + 'V-' + (Get-Size $Hash[$k][2]) + ']';   #后缀
  38.     $sufFix = $sufFix -replace '(?-i)(?<=\D)0[PV]';       #删掉0P、0V
  39.     $newName = $k.Split('\')[-1] + $sufFix;
  40.     Rename-Item -Literal $k -NewName $newName;            #重命名
  41. }
  42. pause
复制代码

作者: walkercolin    时间: 2024-8-26 20:36

本帖最后由 walkercolin 于 2024-8-26 20:37 编辑

回复 13# ppll2030

大佬,很不好意思现在打扰你,按照您的意思修改完代码之后,一开始用的并没有什么问题,但是后面仔细检查时发现计算大小很多时候总是会差个几mb,和资源管理器所显示的大小并不一致,不知道这是为什么
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /d %%a in (*) do (
  4.     set/a p=v=z=0
  5.     pushd "%%a"
  6.     for %%b in (*.jpg *.png *.bmp *.jpeg *.gif) do (
  7.         rem 计算放在这里,就是对所有图片大小的计算
  8.         set/a z+=%%~zb
  9.         if not "%%~nb"=="000" if not "%%~nb"=="00.1" if not "%%~nb"=="00.2" if not "%%~nb"=="00.3" (
  10.             set/a p+=1
  11.         )
  12.     )
  13.     for %%c in (*.mp4 *.avi *.mov *.mkv) do (
  14.         set/a v+=1,z+=%%~zc
  15.     )
  16.     for /f %%v in ('powershell "[math]::Round(!z! / (1073*1000), 0)"') do set "sizeMB=%%v"
  17.     set "sizeUnit=M"
  18.     if !sizeMB! geq 1024 (
  19.         for /f %%v in ('powershell "[math]::Round(!z! / (1073*1000*1000), 2)"') do set "sizeGB=%%v"
  20.         set "sizeUnit=G"
  21.     )
  22.     popd
  23.     if !v! equ 0 (
  24.         rem 没有视频,只有图像
  25.         if "!sizeUnit!"=="G" (
  26.             ren "%%a" "%%a [!p!P-!sizeGB!!sizeUnit!]"
  27.         ) else (
  28.             ren "%%a" "%%a [!p!P-!sizeMB!!sizeUnit!]"
  29.         )
  30.     ) else if !p! equ 0 (
  31.         rem 没有图像,只有视频
  32.         if "!sizeUnit!"=="G" (
  33.             ren "%%a" "%%a [!v!V-!sizeGB!!sizeUnit!]"
  34.         ) else (
  35.             ren "%%a" "%%a [!v!V-!sizeMB!!sizeUnit!]"
  36.         )
  37.     ) else (
  38.         rem 既有图像又有视频
  39.         if "!sizeUnit!"=="G" (
  40.             ren "%%a" "%%a [!p!P!v!V-!sizeGB!!sizeUnit!]"
  41.         ) else (
  42.             ren "%%a" "%%a [!p!P!v!V-!sizeMB!!sizeUnit!]"
  43.         )
  44.     )
  45. )
  46. pause
复制代码

作者: ppll2030    时间: 2024-8-26 21:16

回复 16# walkercolin


    转换进率你可以改一下。
16行的 1073*1000 改为 1024*1024
19行的 1073*1000*1000 改为 1024*1024*1024

或者用上面大佬的进率。第一个该为1mb,第二个改为1tb 这个比较直观。
作者: walkercolin    时间: 2024-8-27 07:23

回复 17# ppll2030
谢谢大佬,现在计算倒是正常的,只不过他会四舍五入158.8他就能继承159mb,当然也不是什么问题,现在的问题是超过2G的内容这玩意儿就有点毛病了,一个2.24g的内容它记成了1796M,一个2.38g的内容记成了1654M,暂不理解为什么
作者: 77七    时间: 2024-8-27 12:10

本帖最后由 77七 于 2024-8-28 13:32 编辑

回复 18# walkercolin


代码中的计算方式是terse大佬的代码,我数学不好,认真看,还是存在数学问题上的鸿沟,即使数学老师在,我估计也要学习很久,所以不想了,只是从for /l 字符串截取不为空的前提下,改动了一下 计算长度,和 for /l 中的结尾数字,不一定对,请多包涵。

  1. @echo off
  2. rem 保存为ansi编码
  3. cd /d "%~dp0"
  4. rem 排除特定文件(000,00.1,00.2,00.3),不需要可以删除下一行
  5. set "_f=^|findstr /rvix /c:"00\.[123]\.[jpb][pnm][gp]" /c:"000\.[jpb][pnm][gp]""
  6. (for /f "delims=" %%d in ('dir /b /ad') do (
  7. setlocal
  8. pushd "%%d"
  9. if not errorlevel 1 (
  10. for /f %%a in ('dir /b /a-d *.jpg *.png *.bmp %_f% ^|find /c /v ""') do (
  11. set /a "1/%%a" && set P=%%aP
  12. )
  13. for /f %%a in ('dir /b /a-d *.mp4 *.avi *.mov *.mkv ^|find /c /v ""') do (
  14. set /a "1/%%a" && set V=%%aV
  15. )
  16. set m=1048576
  17. for /f "eol=0tokens=3" %%j in ('dir /s /a-d /-c *.jpg *.png *.bmp *.mp4 *.avi *.mov *.mkv 2^>nul^| findstr /i "个文件.*字节$"') do (
  18. set size=%%j00
  19. setlocal enabledelayedexpansion
  20. if !size! geq 102400 (
  21. if !size! geq 104857600 (
  22. set s=MB
  23. set t=!size!
  24. set len=!t:~9!9876543210
  25. set /a len=!len:~9,1!+9
  26. set /a "r=!t:~,8!%%m,size=!t:~,8!/m"
  27. set /a len-=1
  28. for /l %%j in (8 1 !len!) do (
  29. set/a "q=!r!!t:~%%j,1!/m,r=!r!!t:~%%j,1!%%m"
  30. set "size=!size!!q!"
  31. )
  32. if !size! geq 102400 set s=GB&set /asize/=1024
  33. ) else set s=KB&set /asize/=1024
  34. ) else set s=Byte
  35. for /f "tokens=1-3" %%a in ("!size:~,-2! !size:~-2! !s!") do (
  36. endlocal
  37. set Z=%%a.%%b%%c
  38. )
  39. )
  40. popd
  41. if defined Z (
  42. call echo ren "%%d" "%%d [%%p%%%%V%%-%%Z%%]"
  43. )
  44. )
  45. endlocal
  46. )) 2>nul
  47. pause
复制代码

作者: ppll2030    时间: 2024-8-27 13:52

回复 18# walkercolin


    终于看到你提出这个问题了。多次提醒你2G的限制,我就纳闷了。这么久了你都没碰到过这个问题

赶紧更换代码,楼上很多大佬都有给出了的。

多种情况更名,你喜欢的也可以保留自己的那部分,改一改变量,衔接上即可。毕竟是自己的更亲一点吧:lol
作者: walkercolin    时间: 2024-8-27 14:47

回复 20# ppll2030

实在抱歉,大佬,我想应该是理解上的误差,因为直到现在我才能看懂部分所说的内容,而这里的看懂甚至不是指的看懂代码,一方面是由于我真的什么代码都看不懂所以导致无法正确理解你们在说什么,还有就是大佬认为的我不懂和我认为的我不懂有那么些许差别,实在对不起,在这里万分感谢各位的帮助,谢谢了




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