Board logo

标题: [文件操作] [已解决]批处理文件已存在则添加序号 [打印本页]

作者: adfs945    时间: 2023-7-19 14:29     标题: [已解决]批处理文件已存在则添加序号

各位大佬大家好:

以下是小弟写的最简单的批处理命令:将AAA文件夹里面的内容剪切到BBB文件夹
move C:\Users\dmns25163\Desktop\AAA\*.* C:\Users\dmns25163\Desktop\BBB

当两个文件名相同的时候希望能有些区分,目前想到的届时增加尾缀。
例:新建 Microsoft Access 数据库→新建 Microsoft Access 数据库1→新建 Microsoft Access 数据库2(以此类推)

希望大神给与指导。
作者: BingjianREMIX    时间: 2023-7-19 16:11

回复 1# adfs945


    之前已经有过类似的了,要善于搜索
  1. @echo off
  2. set /p yourprogramname=what your program name:
  3. :start
  4. cd /d "%~dp0"
  5. if not exist %yourprogramname%.txt (
  6.     set /a "fx=0"
  7. )
  8. if exist "%yourprogramname%.txt" (
  9.    set /a "fx=0"
  10.    set /a "b=1"
  11.    set /a "fx=%fx%+1"
  12.    set "OutFile=%yourprogramname%%fx%.txt"
  13. )
  14. if "%fx%" equ "0" (
  15.        set "OutFile=%yourprogramname%.txt"
  16. )
  17. :1
  18. (for /f "delims=" %%i in ('dir /b /a-d *.*') do (
  19.     if "%%i" neq "%OutFile%" (
  20.         echo,%%~ni
  21.     )
  22. ))>"%OutFile%"
  23. if exist "%yourprogramname%0 .txt" (
  24.    ren "%yourprogramname%0.txt" "%yourprogramname%1 .txt"
  25. )
  26. pause >nul
  27. goto start
复制代码
这个脚本会给出一个类似"文件名0.txt"的,如果不用的话就在进下一个循环的时候改掉"文件名1.txt"
作者: 77七    时间: 2023-7-19 17:38

  1. @echo off
  2. rem 批处理保存为ansi编码格式
  3. set "folder1=C:\Users\dmns25163\Desktop\AAA"
  4. set "folder2=C:\Users\dmns25163\Desktop\BBB"
  5. for %%a in ("%folder1%\*.*") do (
  6. if not exist "%folder2%\%%~nxa" (
  7. move "%%a" "%folder2%"
  8. ) else (
  9. call :1
  10. )
  11. )
  12. pause
  13. exit
  14. :1
  15. for /l %%l in (2,1,200) do (
  16. if not exist "%folder2%\%%~na(%%l)%%~xa" (
  17. move "%%a" "%folder2%\%%~na(%%l)%%~xa"
  18. exit /b
  19. )
  20. )
复制代码

我在写脚本中,发现一个问题。在此请教一下路过的老师、大佬,为什么我把200改为2000000,移动完一个文件后会等待很久才继续移动下一个?echo %%l观察了一下,并没有在循环中,但是实际还是在执行for /l 的循环,数字越大等待越久。
作者: Batcher    时间: 2023-7-19 21:34

回复 3# 77七


    参考:http://bbs.bathome.net/thread-2411-1-1.html#pid14477
作者: 447219071    时间: 2023-7-19 21:38

  1. @echo off  
  2. set source=C:\Users\dmns25163\Desktop\AAA  
  3. set destination=C:\Users\dmns25163\Desktop\BBB
  4. mkdir %destination%
  5. for /r "%source%" %%a in (*) do (  
  6.    set file=%%~nxa  
  7.    if exist "%destination%\%file%" (  
  8.        set /a i=1  
  9.        for %%b in ("%destination%\%~nxa") do (  
  10.            set /a i+=1  
  11.            ren "%destination%\%~nxa" "%destination%\%~nxa!i!"  
  12.        )  
  13.    ) else (  
  14.        move /y "%source%\%%a" "%destination%\%%a"  
  15.    )  
  16. )
复制代码
这段代码首先创建一个名为 BBB 的新文件夹(如果还不存在),然后进入 AAA 文件夹及其子文件夹。对于每个文件,它首先检查目标文件夹中是否已经存在同名的文件。如果存在,则在文件名后加上一个数字,以区分它们。如果没有,则将文件移动到目标文件夹。
请注意,这个批处理文件假设源文件夹(AAA)和目标文件夹(BBB)都在您的桌面上。如果您希望更改这些文件夹的路径,请更改 `set source` 和 `set destination` 行中的路径。
作者: Batcher    时间: 2023-7-19 22:00

回复 5# 447219071


    这代码是错的,你试试就知道了。
作者: 77七    时间: 2023-7-19 22:10

本帖最后由 77七 于 2023-7-19 22:27 编辑

回复 4# Batcher


   

谢谢站长指点!不过我没明白,我使用exit /b 退出了,应该不会对,2-200全部遍历了吧?
  1. @echo off
  2. for /l %%l in (2,1,200) do (
  3.         >>123.txt echo 1
  4.         exit
  5. )
复制代码


比如把这个代码单独拿出来,文本也只会产生一个1。
  1. @echo off
  2. for /l %%l in (2,1,2000000) do (
  3.         >>123.txt echo 1
  4.         exit
  5. )
复制代码


像这样,脚本也是一闪而过就执行完毕,为什么用call之后要等很久?
作者: 77七    时间: 2023-7-19 22:34

回复 4# Batcher


   站长,我把脚本简化了一下,方便测试
  1. @echo off
  2. echo %time%
  3. call :1
  4. echo %time%
  5. pause
  6. exit
  7. :1
  8. for /l %%l in (2,1,2000000) do (
  9. echo 1
  10. exit /b
  11. )
复制代码

作者: qixiaobin0715    时间: 2023-7-20 10:03

回复 7# 77七
call调用另一个批处理程序或自身程序段,调用完后,程序会回到原来的位置继续执行下去。
作者: WHY    时间: 2023-7-20 10:22

回复 8# 77七


    把 exit /b 改成 exit 就能看出区别
在批处理脚本中,exit 是退出 cmd.exe,而 exit /b 与 goto :EOF 几乎等效,跳转到批处理结尾。
作者: 77七    时间: 2023-7-20 10:35

回复 9# qixiaobin0715


   谢谢大佬指点!我的问题主要如8楼所示,我执行需要5秒,找不到原因。
作者: 77七    时间: 2023-7-20 10:39

回复 10# WHY


      谢谢大佬指点!我不理解的是为什么执行8楼的脚本需要5秒?
作者: WHY    时间: 2023-7-20 10:47

回复 12# 77七


    你可以这样理解:
遇到 exit,for /L 循环中的变量不会继续迭代,立马退出 cmd.exe
否则,for /L 循环中的变量会继续迭代,即使遇到 goto :EOF 或 exit/b 也是如此。
作者: qixiaobin0715    时间: 2023-7-20 10:49

回复 11# 77七
应当和call关系不大,可能是与预处理有关,单独试试最后一段for循环:
  1. for /l %%l in (2,1,2000000) do (
  2. echo 1
  3. exit /b
  4. )
复制代码
同样会
作者: 77七    时间: 2023-7-20 11:24

回复 13# WHY

谢谢大佬指点!看来for /l 中使用 exit /b 或 goto 比较特殊,会增加不必要的迭代时间。
作者: 77七    时间: 2023-7-20 11:28

回复 14# qixiaobin0715

谢谢大佬指点!
  
  1. @echo off
  2. for /l %%l in (2,1,2000000) do (
  3. echo 1
  4. goto :2
  5. )
  6. :2
  7. echo 2
  8. pause
复制代码

像call for /l 用的可能少一点,但像上面的代码,我有时候还是会用到的,以后得谨慎使用过大数字。
作者: adfs945    时间: 2023-7-20 11:33

回复 2# BingjianREMIX

非常感谢指导,接下来我根据自己水平稍微调整一下,因为个主要是针对TXT文件,我是要所有文件。
作者: aloha20200628    时间: 2023-7-20 14:22


如何尽快跳出 for /L 循环》又是一个经典问题。
外网dostips.com就此曾有多次讨论,现简化出三个题型说明一些思路的对比结果,给本坛有兴趣者品味参考...
基本上是毙掉了在循环体内 call :xxx 子过程的方法,因其低效繁复。
个人感觉题型一类似 do-while 循环结构,也许更有实用价值。
  1. ::题型一,采用开关变量 + if 语块包裹循环体》耗时约2s
  2. @echo off
  3. set "#break="
  4. for /L %%n in (1,1,320000) do if not defined #break (
  5.    REM ”其他命令“
  6.    set "n=%%n" &set #break=1)
  7. echo,%n%
  8. ::exit/b
  9. ::题型二,采用 if 语块包裹循环体》约耗时1.5s
  10. @echo off
  11. for /L %%n in (1,1,320000) do if %%n equ 1 (
  12.     REM ”其他命令“
  13.     set "n=%%n" &goto[outLoop])
  14. :[outLoop]
  15. echo,%n%
  16. ::exit/b
  17. ::题型三,不采用 if 语块包裹循环体》耗时约12s
  18. @echo off
  19. for /L %%n in (1,1,3200000) do (
  20. REM ”其他命令“
  21. set "n=%%n" &goto[outLoop])
  22. :[outLoop]
  23. echo,%n%
  24. ::exit/b
复制代码

作者: adfs945    时间: 2023-7-20 14:45

回复 3# 77七

非常感谢指导,测试OK。
另外我又追加了循环10秒运行一回,但是失败了,请继续指导一下。
  1. @echo off
  2. set INTERVAL=10
  3. :Again
  4. rem 批处理保存为ansi编码格式
  5. set "folder1=C:\Users\dmns25163\Desktop\AAA"
  6. set "folder2=C:\Users\dmns25163\Desktop\BBB"
  7. for %%a in ("%folder1%\*.*") do (
  8. if not exist "%folder2%\%%~nxa" (
  9. move "%%a" "%folder2%"
  10. ) else (
  11. call :1
  12. )
  13. )
  14. pause
  15. exit
  16. :1
  17. for /l %%l in (2,1,200) do (
  18. if not exist "%folder2%\%%~na(%%l)%%~xa" (
  19. move "%%a" "%folder2%\%%~na(%%l)%%~xa"
  20. exit /b
  21. )
  22. )
  23.    
  24.     del try.txt
  25.     timeout %INTERVAL%
  26.    
  27.     goto Again  
复制代码

作者: adfs945    时间: 2023-7-20 14:48

回复 5# 447219071


    感谢指导,学习了。
作者: adfs945    时间: 2023-7-20 14:49

回复 4# Batcher


    感谢大佬指点,小白努力学习中。
作者: BingjianREMIX    时间: 2023-7-20 14:51

回复 5# 447219071


    怎么有点像GPT的
作者: BingjianREMIX    时间: 2023-7-20 14:55

回复 17# adfs945


    没事把所有后缀改动一下就行,像*.*
作者: Batcher    时间: 2023-7-20 15:44

回复 19# adfs945


timeout %INTERVAL%
goto Again
你把这两行挪到第17行下面试试
作者: Batcher    时间: 2023-7-20 16:12

回复 18# aloha20200628


    是不是复制错了,为何一和二是4个0,三是5个0?
作者: 77七    时间: 2023-7-20 16:24

回复 18# aloha20200628


   
谢谢老师指点!经过我粗略测试,发现三种方法,仍然没有避免for /l 产生不必要的迭代,细微的时间差别,可能是脚本自身的效率影响。
作者: 77七    时间: 2023-7-20 16:34

回复 19# adfs945


   既然你需要如此频繁使用,将标签部分修改为 set /a +goto 好了,避免 for /l 影响效率,和for /l 数字固定问题。
  1. @echo off
  2. set INTERVAL=10
  3. :Again
  4. rem 批处理保存为ansi编码格式
  5. set "folder1=C:\Users\dmns25163\Desktop\AAA"
  6. set "folder2=C:\Users\dmns25163\Desktop\BBB"
  7. for %%a in ("%folder1%\*.*") do (
  8. if not exist "%folder2%\%%~nxa" (
  9. move "%%a" "%folder2%"
  10. ) else (
  11. set n=1
  12. call :1 "%%a"
  13. )
  14. )
  15. timeout %INTERVAL%
  16. goto Again
  17. pause
  18. exit
  19. :1
  20. set /a n+=1
  21. if not exist "%folder2%\%~n1(%n%)%~x1" (
  22. move "%~1" "%folder2%\%~n1(%n%)%~x1"
  23. exit /b
  24. ) else (
  25. goto :1
  26. )
复制代码

作者: qixiaobin0715    时间: 2023-7-20 17:21

回复 27# 77七
后面代码这样即可:
  1. :1
  2. set /a n+=1
  3. if exist "%folder2%\%~n1(%n%)%~x1" goto :1
  4. move "%~1" "%folder2%\%~n1(%n%)%~x1"
复制代码

作者: 77七    时间: 2023-7-20 17:54

回复 28# qixiaobin0715


   

谢谢大佬指点!大佬的代码更加直观易读。
作者: aloha20200628    时间: 2023-7-20 19:29


代码已作如下订正。看那些纯P老玩家已经不深究 for/L 能否立即退出循环的问题了,切磋的只是如何“尽快”退出的“妙计高招”。for/L 的循环量一旦过万,钝感即现,上十万就相当吃力了... 好在批处理脚本勉为其难的企业级(大数量规模)应用,都有更高效的成熟解决方案,仅脚本而言,前有vbs/jscript/mshta/awk/...,后有powershell/python/... 着实省去了以往纯P非要在“螺蛳壳里作道场”的艰难曲折了...
  1. ::题型一》采用开关变量+if 语块包裹循环体 不用goto》耗时约2s
  2. set "#break="
  3. for /L %%n in (1,1,320000) do if not defined #break (set "n=%%n" &set #break=1)
  4. echo,%n%
  5. pause &exit/b
  6. ::题型二》采用 goto+if 语块包裹循环体》耗时1.6s
  7. for /L %%n in (1,1,320000) do if %%n equ 1 (set "n=%%n" &goto[outLoop])
  8. :[outLoop]
  9. echo,%n%
  10. pause &exit/b
  11. ::题型三》采用 goto,不采用 if 语块包裹循环体》耗时约1s
  12. for /L %%n in (1,1,320000) do (set "n=%%n" &goto[outLoop])
  13. :[outLoop]
  14. echo,%n%
  15. pause &exit/b
复制代码

作者: 77七    时间: 2023-7-20 20:30

回复 30# aloha20200628


   

谢谢老师指点!您的意思我大概理解了,既然无法立即退出for /l 循环,就提高批处理代码效率,使for /l 尽快退出。
作者: adfs945    时间: 2023-7-21 11:24

回复 27# 77七


非常感谢指导,测试OK




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