找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 66447|回复: 17

[文件操作] 批处理如何提高效率:复制源文件夹中新近创建的文件至指定文件夹

[复制链接]
发表于 2022-5-17 18:03:20 | 显示全部楼层 |阅读模式
本帖最后由 alredstone 于 2022-5-18 12:36 编辑

=============== 以下为最近一次编辑的内容 ===============

目标:遍历每个文件获取其创建日期,并和指定日期进行比对,最后复制或跳过。

结论:继续求教更高执行效率的处理办法。


以下为讨论部分:

关于bat执行效率的问题,论坛里有较多讨论,@随风 版主也做了汇总 http://www.bathome.net/thread-4828-1-1.html 。 然而执行效率问题依旧是绕不过的坎。

在坛友 @idwma 的建议下,我尝试将多次调用 call 和 goto 改为 for 和 if 语句,因此也引入了 管道 和 findstr 。最终测试结果发现,两者对于1000个文件的处理,差异不大(3秒以内,重复三次)。

目前可获得的结论如下:重复调用 call 和 goto 与重复使用 管道 和 findstr ,执行效率相当。考虑到 call 和 goto 的使用有助于增加代码的可读性(尤其是对新手而言),在没有更好选择的情况下,建议使用 call 和 goto 。

依据坛友 @idwma 的建议,更改后的代码如下:
  1. :identify_copy
  2. setlocal enabledelayedexpansion
  3. set "tmpdrctry=D:\newfolder"
  4. set strttm=%time%
  5. for /f "tokens=* delims=" %%z in ('dir /s/b/a-d-h-s') do (
  6.         for /f "tokens=1" %%a in ('dir "%%z" /tc ^|findstr /e "%%~xz"') do (
  7.                 set "fpath=%%z"
  8.                 set "fdrctry=%%~dpz"
  9.                 set "fcd=%%a"
  10.                 if "!fcd!" GEQ "2022/01/01" (call set "tmpdrctry2=%%fdrctry:%cd%=%tmpdrctry%%%" &xcopy "!fpath!" "!tmpdrctry2!" /v/s)
  11.                 )
  12.         )
  13. echo Process started at %strttm%, ended at %time%.
  14. pause
复制代码
.



=============== 以下为原帖内容 ===============

操作目标:复制当前文件夹中2022年1月1日之后创建的文件至指定文件夹(D:\newfolder),须保持目录树。

使用代码如下,因多次调用 call 和 goto,导致执行效率很低(总文件数约5000个)。

求教:如何提高执行效率。
  1. :identify_copy
  2. set strttm=%time%
  3. set "tmpdrctry=D:\newfolder"
  4. for /f "tokens=* delims=" %%z in ('dir /s/b/a-d-h-s') do (
  5.         set "fpath=%%z"
  6.         set "fdrctry=%%~dpz"
  7.         call :acqrdt
  8.         )
  9. echo Process started at %strttm%, ended at %time%.
  10. pause

  11. :acqrdt
  12. for /f "skip=4 tokens=1" %%a in ('dir "%fpath%" /tc') do (
  13.         set "fcd=%%a"
  14.         call :dtprcss & goto :EOF
  15.         )

  16. :dtprcss
  17. if "%fcd%" GEQ "2022/01/01" (goto copynf)
  18. goto :EOF

  19. :copynf
  20. call set "tmpdrctry2=%%fdrctry:%sdrctry%=%tmpdrctry%%%"
  21. xcopy "%fpath%" "%tmpdrctry2%" /v/s
  22. goto :EOF
复制代码
发表于 2022-5-17 18:21:57 | 显示全部楼层
  1. xcopy . D:\newfolder /d:1-1-2022 /v/s
复制代码
 楼主| 发表于 2022-5-17 18:26:26 | 显示全部楼层
回复 2# idwma


    xcopy 的 /d 参数是修改日期,不是创建日期。
发表于 2022-5-17 18:32:10 | 显示全部楼层
  1. robocopy . D:\newfolder /maxage:20220101 /s
复制代码
 楼主| 发表于 2022-5-17 18:39:41 | 显示全部楼层
回复 4# idwma


    robocopy 的 maxage 参数,也是修改日期
发表于 2022-5-17 18:50:12 | 显示全部楼层
本帖最后由 idwma 于 2022-5-17 19:23 编辑

  1. setlocal enabledelayedexpansion
  2. set "tmpdrctry=D:\newfolder"
  3. for /f "tokens=* delims=" %%z in ('dir /s/b/a-d-h-s') do (
  4. for /f "skip=4 tokens=1" %%a in ('dir "%%z" /tc') do (
  5.   if "%%a" GEQ "2022/01/01" (
  6.                set "fdrctry=%%~dpz"
  7.         set "fdrctry=!fdrctry:%cd%=!"
  8.         mkdir "%tmpdrctry%!fdrctry!"
  9.         copy "%%z" "%tmpdrctry%!fdrctry!"
  10.   )
  11. )
  12. )
复制代码

评分

参与人数 1技术 +1 收起 理由
alredstone + 1 这个办法不错。感谢!

查看全部评分

 楼主| 发表于 2022-5-17 21:31:27 | 显示全部楼层
本帖最后由 alredstone 于 2022-5-17 23:28 编辑

回复 6# idwma


    说明一下,因对单个文件 dir 的 /tc 结果有 6 行,上述代码直接使用的话会出错,需要添加 |findstr /e "%%~xz"   

    总的来说,非常棒的思路,降低了call、goto的调用。
 楼主| 发表于 2022-5-17 23:27:34 | 显示全部楼层
尴尬的问题出现了,因为 管道 和 findstr 的使用,最终执行效率并没有改善
发表于 2022-5-18 14:12:16 | 显示全部楼层
回复 7# alredstone


    不加findstr也可以的吧, 出什么样的错?
 楼主| 发表于 2022-5-18 16:53:24 | 显示全部楼层
回复 9# idwma


    对单个文件 dir /tc 输出结果一共有 6 行(不计空行),skip=4 只能跳过前 3 行,接着会将 4~6 行的结果赋值给 %%a,即同一个文件会赋值 3 次,导致出错。

这也是我采用的代码中获取创建日期的时候写为 call :dtprcss & goto :EOF 的原因。

对单个文件 dir /tc 输出的信息如下:
  1. 驱动器属性
  2. 卷序号

  3. 文件所在目录

  4. 文件创建日期 时间 大小 文件名
  5. 目录内文件个数 大小
  6. 包含目录个数 卷剩余容量
复制代码
发表于 2022-5-18 17:03:12 | 显示全部楼层
6楼代码第5行难道是吃素的?不知楼主是否实际测试过。
发表于 2022-5-18 17:10:43 | 显示全部楼层
这种情况好像只能在源文本中测试,因为在备份文件中测试,创建时间就变成备份时的时间了。
发表于 2022-5-18 17:22:46 | 显示全部楼层
第8行改一下应该不提示出错了吧
  1. mkdir "%tmpdrctry%!fdrctry!" 2>nul
复制代码
 楼主| 发表于 2022-5-18 17:26:29 | 显示全部楼层
回复 11# qixiaobin0715


    别着激动嘛

  if "%%a" GEQ "2022/01/01" 这句是将 %%a 的值与字符串 2022/01/01 进行比较。在本帖讨论的条件下,对于每个文件而言 %%a 会被赋值 3 次,即后面的命令也会重复 3 次。

即除了 创建时间 会被赋值给 %%a 外,目录内的文件数目录数同样也会被赋值给 %%a 并与字符串 2022/01/01 进行比较。因此会出错。

代码的鲁棒性(Robustness)也是一个需要考虑的因素。
 楼主| 发表于 2022-5-18 17:38:22 | 显示全部楼层
回复 13# idwma


      这样也可以吧,也是一种解决思路。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-20 01:54 , Processed in 0.020001 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表