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

回复 30# aloha20200628


   大佬,for /r "%~1"是我随手写的,如果目录非常庞大,dir /b /ad 没有/s ,没有遍历子目录,显然有失公平,使用/r应该徒增了很多无用功吧,以前我做过测试,for /r 的遍历机制,当处理到第一个(还是第二个,记不清了)目录的时候,大概已经完成了700多个目录的列举,(数据记得不是很清楚了)不知道这是否拉低了效率
麻烦大佬您再测试一下,for /d

  1. set "n="&for /d /r %%d in (*) do (
  2.         set "k=" &(call :xxx "%%~d" k)
  3.         if not defined k set/a "n+=1"
  4. )
  5. echo,发现 %n% 个末级目录&exit/b
  6. :xxx
  7.         for /d %%e in ("%~1\*") do (set "%~2=1"&exit/b)
  8.         exit/b
复制代码
bat小白,请多指教!谢谢!

TOP

本帖最后由 77七 于 2024-4-13 19:31 编辑

回复 30# aloha20200628


   大佬,我把c盘复制了5次66000文件,16000目录,末级目录10000个
测试了方法1、4,结论和大佬的一致
call +for /d 7分钟,dir 4分钟。call cpu占用比dir低。感觉dir在全力跑,call+for /d有点散步的意思
bat小白,请多指教!谢谢!

TOP

本帖最后由 aloha20200628 于 2024-4-13 22:11 编辑

回复 31# 77七

只要用call方法
   for /d %%d in ("%~1\*") do (set "%~2=1"&exit/b)

   for /d /r "%~1" %%d in (*) do (set "%~2=1"&exit/b)
两个句式的耗时差约在 0.07~0.05%,二者基本相当吧。
结论还是》一方面,得益于用call方法能使纯P代码从for循环中及时退出;另一方面,跑大体量数据到其“拐点”后就“怂”了...

TOP

这样CALL,系统开销是否会有所不同呢
  1. @echo off
  2. call :listdir "%cd%"
  3. echo %n%
  4. pause
  5. exit
  6. :listdir
  7. for /d %%d in ("%~1\*") do (
  8.     set "d=%%d"
  9.     call :listdir "%%d"
  10. )
  11. if defined d (
  12.    set /an+=1
  13. )
  14. set "d="
复制代码

TOP

本帖最后由 77七 于 2024-4-14 01:00 编辑

回复 34# terse


  之前测试效率,被if () 搞中断了...
现在我测试了一下,大佬您的代码效率很高,测试样本仍然是32楼的那些,耗时20秒左右

样本说明:复制了整个c盘小于10kb的文件及目录,并手动复制了几次

可能是因为样本比较特殊,使用中出现了一些小插曲,大佬的代码遗漏了 ”用户\admin\appdata“ 目录下的末级目录
,到
  1. "f:\测试\Users - 副本 - 副本 (2)\admin\3D Objects"
复制代码
就结束了。

而dir 和call +for /d 均列出了
  1. "F:\测试\Users - 副本 - 副本\admin\AppData\Local\Microsoft\PowerShell\7.2.7"
复制代码
bat小白,请多指教!谢谢!

TOP

本帖最后由 77七 于 2024-4-14 01:57 编辑

我找出原因了
用户\admin\appdata
这个目录使用for /r /d 能够遍历出来,使用for /d 则不能
惭愧惭愧,学习不思考......appdata下的子目录不具有隐藏属性,所以for /r /d遍历了appdata下的子目录,仍没有遍历出appdata
bat小白,请多指教!谢谢!

TOP

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


用本帖到目前为止的3种典型的call方法(代码如下)再跑了几遍测试样本,与30楼所列方法1-3测试数据合并,能有一个更全面的结论...致谢30楼和36楼
  1. ::方法4
  2. set "n="&for /d /r %%d in (*) do (
  3. set "k=" &(call :x4 "%%~d" k)
  4. if not defined k set/a "n+=1"
  5. )
  6. echo,发现 %n% 个末级目录&pause&exit/b
  7. :x4
  8. for /d /r "%~1" %%d in (*) do (set "%~2=1"&exit/b)
  9. exit/b
复制代码
  1. ::方法5
  2. set "n="&for /d /r %%d in (*) do (
  3. set "k=" &(call :x5 "%%~d" k)
  4. if not defined k set/a "n+=1"
  5. )
  6. echo,发现 %n% 个末级目录&pause&exit/b
  7. :x5
  8. for /d %%d in ("%~1\*") do (set "%~2=1"&exit/b)
  9. exit/b
复制代码
  1. ::方法6
  2. set "n="&(call :x6 "%cd%")
  3. echo,发现 %n% 个末级目录&pause&exit/b
  4. :x6
  5. for /d %%d in ("%~1\*") do (set "d=%%d"&call :x6 "%%d")
  6. if defined d (set /a n+=1)
  7. set "d="&exit/b
复制代码
方法1-6测试数据合并如下
测试主目录及其文件和子目录体量                        方法1耗时/方法2耗时/方法3耗时/方法4耗时/方法5耗时/方法6耗时(耗时单位=秒)
c:\a1 148,814 个文件,32,751 个文件夹        255/275/783/1239/1149/741
c:\a2  30,262 个文件, 3,281 个文件夹        21/24/26/14/14/4
c:\a3  28,159 个文件, 2,114 个文件夹        13/15/15/6/6/2
c:\a4  16,916 个文件, 1,213 个文件夹        8/9/8/2/2/1
可见方法6采用了递归调用,没有方法4-5代码中宿主循环开销,效率倍增,但依然会在a1-a2样本之间遭遇 ‘拐点爆胎’,被方法1-2赶超...
另一点是如36楼所说会遗漏那些受保护(如隐藏)目录...
》以上仅供参考,有兴趣者还可参考以下老帖,融合体会一下call先生的功与过...
   一。批处理之家 » BAT教程&资料 » 讨论:批处理运行效率浅谈
   二。http://bbs.bathome.net/thread-4482-1-1.html
2

评分人数

TOP

回复 37# aloha20200628
差距这么大,也许环境和目录结构的不同,测试结构也会不同,下面代码创建的空目录试了一下,相比较还好CALL并不是太耗资源,
  1. for /l %%a in (1,1,10) do  for /l %%b in (1,1,10) do for /l %%c in (1,1,10) do for /l %%d in (1,1,10) do for /l %%e in (1,1,10) do md test\%%a\%%b\%%c\%%d\%%e\ 2>nul   
复制代码

TOP

返回列表