[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[文件操作] 批处理统计文件夹内的图片视频,计算大小时如何统计单位为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,不知道是否可行拜托各位大佬了

回复 20# ppll2030

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

TOP

回复 18# walkercolin


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

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

多种情况更名,你喜欢的也可以保留自己的那部分,改一改变量,衔接上即可。毕竟是自己的更亲一点吧:lol
1

评分人数

TOP

本帖最后由 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
复制代码
1

评分人数

bat小白,请多指教!谢谢!

TOP

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

TOP

回复 16# walkercolin


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

或者用上面大佬的进率。第一个该为1mb,第二个改为1tb 这个比较直观。

TOP

本帖最后由 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
复制代码

TOP

本帖最后由 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
复制代码
1

评分人数

TOP

只用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
复制代码
bat小白,请多指教!谢谢!

TOP

回复 12# walkercolin


    嗯。楼上的大佬提醒了。你的前半段统计体积,还是用的set/a,所以2GB的限制还是存在的,建议更换dir来获取

TOP

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

TOP

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

回复 1# walkercolin

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

TOP

本帖最后由 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行,正常替换,保留两位小数。
这样应该没有问题了。
1

评分人数

    • walkercolin: 感谢给帖子标题标注[已解决]字样技术 + 1

TOP

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

TOP

本帖最后由 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"
复制代码

TOP

返回列表