标题: [文件操作] [已解决]批处理文件已存在则添加序号 [打印本页]
作者: 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
之前已经有过类似的了,要善于搜索- @echo off
- set /p yourprogramname=what your program name:
- :start
- cd /d "%~dp0"
- if not exist %yourprogramname%.txt (
- set /a "fx=0"
- )
- if exist "%yourprogramname%.txt" (
- set /a "fx=0"
- set /a "b=1"
- set /a "fx=%fx%+1"
- set "OutFile=%yourprogramname%%fx%.txt"
- )
- if "%fx%" equ "0" (
- set "OutFile=%yourprogramname%.txt"
- )
- :1
- (for /f "delims=" %%i in ('dir /b /a-d *.*') do (
- if "%%i" neq "%OutFile%" (
- echo,%%~ni
- )
- ))>"%OutFile%"
- if exist "%yourprogramname%0 .txt" (
- ren "%yourprogramname%0.txt" "%yourprogramname%1 .txt"
- )
- pause >nul
- goto start
复制代码
这个脚本会给出一个类似"文件名0.txt"的,如果不用的话就在进下一个循环的时候改掉"文件名1.txt"
作者: 77七 时间: 2023-7-19 17:38
- @echo off
- rem 批处理保存为ansi编码格式
- set "folder1=C:\Users\dmns25163\Desktop\AAA"
- set "folder2=C:\Users\dmns25163\Desktop\BBB"
- for %%a in ("%folder1%\*.*") do (
- if not exist "%folder2%\%%~nxa" (
- move "%%a" "%folder2%"
- ) else (
- call :1
- )
- )
- pause
- exit
-
- :1
- for /l %%l in (2,1,200) do (
- if not exist "%folder2%\%%~na(%%l)%%~xa" (
- move "%%a" "%folder2%\%%~na(%%l)%%~xa"
- exit /b
- )
- )
复制代码
我在写脚本中,发现一个问题。在此请教一下路过的老师、大佬,为什么我把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
- @echo off
- set source=C:\Users\dmns25163\Desktop\AAA
- set destination=C:\Users\dmns25163\Desktop\BBB
- mkdir %destination%
- for /r "%source%" %%a in (*) do (
- set file=%%~nxa
- if exist "%destination%\%file%" (
- set /a i=1
- for %%b in ("%destination%\%~nxa") do (
- set /a i+=1
- ren "%destination%\%~nxa" "%destination%\%~nxa!i!"
- )
- ) else (
- move /y "%source%\%%a" "%destination%\%%a"
- )
- )
复制代码
这段代码首先创建一个名为 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全部遍历了吧?
- @echo off
- for /l %%l in (2,1,200) do (
- >>123.txt echo 1
- exit
- )
复制代码
比如把这个代码单独拿出来,文本也只会产生一个1。
- @echo off
- for /l %%l in (2,1,2000000) do (
- >>123.txt echo 1
- exit
- )
复制代码
像这样,脚本也是一闪而过就执行完毕,为什么用call之后要等很久?
作者: 77七 时间: 2023-7-19 22:34
回复 4# Batcher
站长,我把脚本简化了一下,方便测试- @echo off
- echo %time%
- call :1
- echo %time%
- pause
- exit
-
- :1
- for /l %%l in (2,1,2000000) do (
- echo 1
- exit /b
- )
复制代码
作者: 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循环:- for /l %%l in (2,1,2000000) do (
- echo 1
- exit /b
- )
复制代码
同样会
作者: 77七 时间: 2023-7-20 11:24
回复 13# WHY
谢谢大佬指点!看来for /l 中使用 exit /b 或 goto 比较特殊,会增加不必要的迭代时间。
作者: 77七 时间: 2023-7-20 11:28
回复 14# qixiaobin0715
谢谢大佬指点!
- @echo off
- for /l %%l in (2,1,2000000) do (
- echo 1
- goto :2
- )
- :2
- echo 2
- 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 循环结构,也许更有实用价值。- ::题型一,采用开关变量 + if 语块包裹循环体》耗时约2s
- @echo off
- set "#break="
- for /L %%n in (1,1,320000) do if not defined #break (
- REM ”其他命令“
- set "n=%%n" &set #break=1)
- echo,%n%
- ::exit/b
-
- ::题型二,采用 if 语块包裹循环体》约耗时1.5s
- @echo off
- for /L %%n in (1,1,320000) do if %%n equ 1 (
- REM ”其他命令“
- set "n=%%n" &goto[outLoop])
- :[outLoop]
- echo,%n%
- ::exit/b
-
- ::题型三,不采用 if 语块包裹循环体》耗时约12s
- @echo off
- for /L %%n in (1,1,3200000) do (
- REM ”其他命令“
- set "n=%%n" &goto[outLoop])
- :[outLoop]
- echo,%n%
- ::exit/b
复制代码
作者: adfs945 时间: 2023-7-20 14:45
回复 3# 77七
非常感谢指导,测试OK。
另外我又追加了循环10秒运行一回,但是失败了,请继续指导一下。- @echo off
-
- set INTERVAL=10
-
- :Again
-
- rem 批处理保存为ansi编码格式
- set "folder1=C:\Users\dmns25163\Desktop\AAA"
- set "folder2=C:\Users\dmns25163\Desktop\BBB"
- for %%a in ("%folder1%\*.*") do (
- if not exist "%folder2%\%%~nxa" (
- move "%%a" "%folder2%"
- ) else (
- call :1
- )
- )
- pause
- exit
-
- :1
- for /l %%l in (2,1,200) do (
- if not exist "%folder2%\%%~na(%%l)%%~xa" (
- move "%%a" "%folder2%\%%~na(%%l)%%~xa"
- exit /b
- )
- )
-
-
- del try.txt
-
- timeout %INTERVAL%
-
- 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 数字固定问题。- @echo off
-
- set INTERVAL=10
-
- :Again
-
- rem 批处理保存为ansi编码格式
- set "folder1=C:\Users\dmns25163\Desktop\AAA"
- set "folder2=C:\Users\dmns25163\Desktop\BBB"
- for %%a in ("%folder1%\*.*") do (
- if not exist "%folder2%\%%~nxa" (
- move "%%a" "%folder2%"
- ) else (
- set n=1
- call :1 "%%a"
- )
- )
- timeout %INTERVAL%
- goto Again
-
- pause
- exit
-
- :1
- set /a n+=1
- if not exist "%folder2%\%~n1(%n%)%~x1" (
- move "%~1" "%folder2%\%~n1(%n%)%~x1"
- exit /b
- ) else (
- goto :1
- )
复制代码
作者: qixiaobin0715 时间: 2023-7-20 17:21
回复 27# 77七
后面代码这样即可:- :1
- set /a n+=1
- if exist "%folder2%\%~n1(%n%)%~x1" goto :1
- 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非要在“螺蛳壳里作道场”的艰难曲折了...- ::题型一》采用开关变量+if 语块包裹循环体 不用goto》耗时约2s
- set "#break="
- for /L %%n in (1,1,320000) do if not defined #break (set "n=%%n" &set #break=1)
- echo,%n%
- pause &exit/b
-
- ::题型二》采用 goto+if 语块包裹循环体》耗时1.6s
- for /L %%n in (1,1,320000) do if %%n equ 1 (set "n=%%n" &goto[outLoop])
- :[outLoop]
- echo,%n%
- pause &exit/b
-
- ::题型三》采用 goto,不采用 if 语块包裹循环体》耗时约1s
- for /L %%n in (1,1,320000) do (set "n=%%n" &goto[outLoop])
- :[outLoop]
- echo,%n%
- 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 |