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

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

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

  1. xcopy . D:\newfolder /d:1-1-2022 /v/s
复制代码

TOP

回复 2# idwma


    xcopy 的 /d 参数是修改日期,不是创建日期。

TOP

  1. robocopy . D:\newfolder /maxage:20220101 /s
复制代码

TOP

回复 4# idwma


    robocopy 的 maxage 参数,也是修改日期

TOP

本帖最后由 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

评分人数

TOP

本帖最后由 alredstone 于 2022-5-17 23:28 编辑

回复 6# idwma


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

    总的来说,非常棒的思路,降低了call、goto的调用。

TOP

尴尬的问题出现了,因为 管道 和 findstr 的使用,最终执行效率并没有改善

TOP

回复 7# alredstone


    不加findstr也可以的吧, 出什么样的错?

TOP

回复 9# idwma


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

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

对单个文件 dir /tc 输出的信息如下:
  1. 驱动器属性
  2. 卷序号
  3. 文件所在目录
  4. 文件创建日期 时间 大小 文件名
  5. 目录内文件个数 大小
  6. 包含目录个数 卷剩余容量
复制代码

TOP

6楼代码第5行难道是吃素的?不知楼主是否实际测试过。

TOP

这种情况好像只能在源文本中测试,因为在备份文件中测试,创建时间就变成备份时的时间了。

TOP

第8行改一下应该不提示出错了吧
  1. mkdir "%tmpdrctry%!fdrctry!" 2>nul
复制代码

TOP

回复 11# qixiaobin0715


    别着激动嘛

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

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

代码的鲁棒性(Robustness)也是一个需要考虑的因素。

TOP

回复 13# idwma


      这样也可以吧,也是一种解决思路。

TOP

返回列表