标题: [文件操作] [已用解压参数设置方式解决]求批处理移动文件代码优化或更简单其它有效方法 [打印本页]
作者: hfxiang 时间: 2022-8-13 11:49 标题: [已用解压参数设置方式解决]求批处理移动文件代码优化或更简单其它有效方法
本帖最后由 hfxiang 于 2022-8-15 07:57 编辑
需要:每隔一段时间会收到一百多个压缩数据包,每个包当中有不确定个数的文件,解压后还存在子文件夹,之前无重名文件,就用以下简单指令(直接在cmd命令行下执行)即可把文件从子文件夹移动到当前文件夹,- for /r %a in (*) do move /y "%a" .
复制代码
之后删除所有子文件夹即可。
但随着文件数量增加,出现许多重名文件,以上指令将会用新文件覆盖原有的同名文件,故写了以下脚本(详见“3.移动文件到当前文件夹代码”)来解决,但总觉得其执行效率实在太低(不作信息回显提升亦不明显),希望有大神能给予优化,或指引一下更简单其它有效方法,不胜感激。
创建测试文件需用到第3方工具seq.exe,下载地址:http://bcn.bathome.net/tool/seq.exe
1.创建100个文件夹(直接在cmd命令行下执行)- (for /f "usebackq tokens=*" %a in (`seq -f "%cd%\Folder%03g" 1 100 2^>nul`) do @mkdir "%a")>nul 2>&1
复制代码
2.在每个子文件夹下创建10个(空)文件(test001.dat~test010.dat)(直接在cmd命令行下执行)- (for /d %a in ("%cd%\*") do @for /f "usebackq tokens=*" %b in (`seq -f "%a\test%03g.dat" 1 10 2^>nul`) do @echo;2>%b)>nul 2>&1
复制代码
3.移动文件到当前文件夹代码(也就是希望优化或另劈方法的地方)- @echo off
- setlocal enableDelayedExpansion
- set /a fn0=0
- set /a fn1=0
- set /a fn2=0
- set /a fn3=0
-
- set "Folder=%~dp0"
- set "Dir_a=%~a1"
- if defined Dir_a if "[%Dir_a:~0,1%]"=="[d]" (
- set "Folder=%~f1"
- ) else (
- set "Folder=%~dp1"
- )
- if /i "[%Folder:~-1,1%]"=="[\]" if /i not "[%Folder:~-2,1%]"=="[:]" set "Folder=%Folder:~0,-1%"
- cd /d "%Folder%"
- for /f "delims==" %%a in ('set exist_File_ 2^>nul') do set "%%a="
- for /f %%a in ('dir /b/a-d') do set "exist_File_%%a=True"
- for /f %%a in ('dir /b/a-d/s') do if /i not [%%~dpa]==[%cd%\] (
- set "Check=True"
- if not defined exist_File_%%~nxa (
- set "exist_File_%%~nxa=True"
- set new_FileName=%cd%\%%~nxa
- ) else (
- call :No_DupFile "%%~na" "%%~xa" newFileName Check
- if /i [!Check!]==[True] set "exist_File_!newFileName!=True"
- set new_FileName=%cd%\!newFileName!
- )
- set /a fn0+=1
- echo;!fn0! "%%a" --^> "!new_FileName!"
- if /i [!Check!]==[True] (
- (
- move /y "%%a" "!new_FileName!">nul 2>&1
- ) && (
- set /a fn1+=1
- echo; 移动成功
- ) || (
- set /a fn2+=1
- echo; 移动失败
- )
- ) else (
- set /a fn3+=1
- echo; 改名失败
- )
- )
- echo;
- if %fn0% GTR 0 echo;待移动文件: %fn0% 个
- if %fn1% GTR 0 echo;移动成功: %fn1% 个文件
- if %fn2% GTR 0 echo;移动失败:%fn2% 个文件
- if %fn3% GTR 0 echo;改名失败:%fn3% 个文件
- endlocal
- echo;&pause
- exit /b
-
- :No_DupFile <oldFileName> <extName> [newFileName] [Check_ID]
- setlocal enableDelayedExpansion
- set "Check=False"
- for /l %%b in (1,1,999) do (
- set n=00%%b
- set n=!n:~-3!
- if not defined exist_File_%~1__!n!%~2 (
- set "FileName=%~1__!n!%~2"
- set "Check=True"
- goto :end_Loop
- )
- )
- :end_Loop
- endlocal&set "%3=%FileName%"&set "%4=%Check%"&goto :EOF
复制代码
作者: hfxiang 时间: 2022-8-14 18:39
几经寻找,从DOS Batch - Function Tutorial( https://www.dostips.com/DtTutoFu ... .RecursiveFunctions )中得到启示,使用递归方式处理,子过程避免使用 setlocal enableDelayedExpansion 启用 "延迟环境变量扩展" ,运行性能出现明显提升,请大神们指导。改进后代码如下:- @echo off
- setlocal enableDelayedExpansion
- set /a fn0=0
- set /a fn1=0
- set /a fn2=0
- set /a fn3=0
-
- set "Folder=%~dp0"
- set "Dir_a=%~a1"
- if defined Dir_a if "[%Dir_a:~0,1%]"=="[d]" (
- set "Folder=%~f1"
- ) else (
- set "Folder=%~dp1"
- )
- if /i "[%Folder:~-1,1%]"=="[\]" if /i not "[%Folder:~-2,1%]"=="[:]" set "Folder=%Folder:~0,-1%"
- cd /d "%Folder%"
-
- for /f "delims==" %%a in ('set exist_File_ 2^>nul') do set "%%a="
- for /f %%a in ('dir /b/a-d') do set "exist_File_%%a=True"
- for /f %%a in ('dir /b/a-d/s') do if /i not [%%~dpa]==[%cd%\] (
- set "Check=True"
- if not defined exist_File_%%~nxa (
- set "exist_File_%%~nxa=True"
- set new_FileName=%cd%\%%~nxa
- ) else (
- set /a P_Serial=0
- call :No_DupFile "%%~na","%%~xa",P_Serial,Serial
- set "exist_File_%%~na__!Serial!%%~xa=True"
- if !P_Serial! GTR 999 set "Check=False"
- set new_FileName=%cd%\%%~na__!Serial!%%~xa
- )
- set /a fn0+=1
- echo;!fn0! "%%a" --^> "!new_FileName!"
- if /i [!Check!]==[True] (
- (
- move /y "%%a" "!new_FileName!">nul 2>&1
- ) && (
- set /a fn1+=1
- echo; 移动成功
- ) || (
- set /a fn2+=1
- echo; 移动失败
- )
- ) else (
- set /a fn3+=1
- echo; 改名失败
- )
- )
-
- echo;
- if %fn0% GTR 0 echo;发现文件: %fn0% 个
- if %fn1% GTR 0 echo;移动成功: %fn1% 个文件
- if %fn2% GTR 0 echo;移动失败:%fn2% 个文件
- if %fn3% GTR 0 echo;改名失败:%fn3% 个文件
- endlocal
- echo;&pause
- exit /b
-
- :No_DupFile <FileName>,<extName>,[P_Serial],[Serial]
- setlocal
- set /a P_Serial=1+%~3
- set Serial=00%P_Serial%
- set Serial=%Serial:~-3%
- if %P_Serial% LEQ 999 if defined exist_File_%~1__%Serial%%~2 call :No_DupFile "%~1","%~2",P_Serial,Serial
- (endlocal
- SET "%3=%P_Serial%"
- SET "%4=%Serial%"
- )
- goto :EOF
复制代码
作者: idwma 时间: 2022-8-14 19:59
解压命令里不是有自动重命名和所有文件放到一个目录的参数吗
作者: hfxiang 时间: 2022-8-15 07:36
本帖最后由 hfxiang 于 2022-8-15 07:37 编辑
回复 3# idwma
这样重名文件能自动改名吗?如果这样就可用压缩再解压的方式解决问题。俺要试一下。谢谢
作者: qixiaobin0715 时间: 2022-8-15 09:53
回复 4# hfxiang
刚才的代码有问题,重发一下。根据一位大佬的代码修改而成,未经测试:- @echo off
- for /d %%a in (*) do (
- pushd "%%a"
- for /f "delims=" %%i in ('dir /s /b /a-d') do (
- set "filename=%%~ni"
- setlocal enabledelayedexpansion
- if not exist "%~dp0!filename!%%~xi" (
- copy "%%i" "%~dp0"
- ) else (
- set "n=1"
- call :Next "%%~xi"
- copy "%%i" "%~dp0!filename!(!n!)%%~xi"
- )
- endlocal
- )
- popd
- )
- pause & exit
- :Next
- if exist "%~dp0!filename!(!n!)%~1" (
- set /a n+=1
- goto :Next
- )
复制代码
作者: hfxiang 时间: 2022-8-15 10:17
回复 5# qixiaobin0715
感谢回复。谢谢。
但[if exist "%~dp0!filename!(!n!)%~1"]代码俺不太敢用,之前经无数次测试,其在文件量大时,效率实在无法接受。
作者: qixiaobin0715 时间: 2022-8-15 10:42
我觉得使用call跳出循环体可能在效率上会有一些损失,但你在1、2楼的代码中for循环的in中使用了'set'命令,循环体中多处使用了组合命令||和&&才是效率低下的主要原因。
作者: hfxiang 时间: 2022-8-15 11:55
回复 7# qixiaobin0715
你说得很对,这些指令会有效率损失,但[if exist ]要访问磁盘,这个访问多了,其效率损失会让人无法接受
作者: qixiaobin0715 时间: 2022-8-15 12:10
本帖最后由 qixiaobin0715 于 2022-8-15 13:32 编辑
回复 8# hfxiang
搜索文件没你想象的那么慢。
单独测试了一下此语句,十万个文件瞬间完成。
作者: hfxiang 时间: 2022-8-15 16:37
回复 9# qixiaobin0715
哪是你的硬盘IO非常强大,俺的硬盘读写是明显感觉到一跳一跳的 ,时时让俺心惊肉跳的
作者: qixiaobin0715 时间: 2022-8-15 16:56
回复 10# hfxiang
应当是在for循环中使用call命令的原因。见帖子:
http://bbs.bathome.net/viewthread.php?tid=4831&from=favorites
中的:
第一大条中第1小条的描述。
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |