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

[文本处理] 求助批处理从文件夹中比对新增的xml文件时间戳,然后拷贝文件,求帮忙优化脚本。

本帖最后由 licunwei 于 2024-5-27 18:03 编辑

以下脚本是通过比对D:\SCETC\dataXml\路径下最新的*602和*603文件时间戳,如果2个文件的修改时间在1秒内,不执行任何动作。如果大于1秒就拷贝*603文件。我用了goto循环,虽然可以比对,但还是经常把2个文件 修改时间在1秒内的*603拷贝走了,我打算后面超过1秒的就拷贝后删除源文件,但现在测试都经常出错,更不敢添加删除命令了。求大神帮忙优化优化。
下面是当前脚本,求优化。
  1. @echo off
  2. if "%1"=="hide" goto :ExecBat
  3. start mshta vbscript:createobject("wscript.shell").run("""%~f0"" hide",0)(window.close) && exit /b
  4. :ExecBat
  5. setlocal enabledelayedexpansion
  6. set "folder=D:\SCETC\dataXml\"
  7. set timestamp_602=0
  8. set timestamp_603=0
  9. set /a m=0
  10. set /a n=0
  11. for /F %%a in ('dir /b /s /o-d %folder%*602.xml') do (
  12.     set /a m+=1
  13.     set "timestamp_602!m!=%%~ta"
  14. )
  15. for /F %%b in ('dir /b /s /o-d %folder%*603.xml') do  (
  16.     set /a n+=1
  17.     set "timestamp_603!n!=%%~tb"
  18. )
  19. set timestamp_602_hh=!timestamp_6021:~11,2!
  20. set timestamp_602_nn=!timestamp_6021:~14,2!
  21. set timestamp_602_formatted=!timestamp_602_hh!!timestamp_602_nn!
  22. set timestamp_603_hh=!timestamp_6031:~11,2!
  23. set timestamp_603_nn=!timestamp_6031:~14,2!
  24. set timestamp_603_formatted=!timestamp_603_hh!!timestamp_603_nn!
  25. set var602=!timestamp_602_formatted:~1!
  26. set var603=!timestamp_603_formatted:~1!
  27. set /a time_diff=%var603% - %var602%
  28. if %time_diff% LSS 1 (
  29.     echo Both *602.xml and *603.xml flow generated within 1 second.
  30. ) else (
  31.     echo Only *603.xml flow generated within 1 second. Deleting latest *603.xml flow...
  32.     for /F %%c in ('dir /b /o-d %folder%*603.xml') do (
  33.       set latest_flow=%%c
  34.       md D:\交易失败流水\%date:~0,4%%date:~5,2%%date:~8,2% 2>nul
  35.       xcopy /y %folder%%%c D:\交易失败流水\%date:~0,4%%date:~5,2%%date:~8,2%\   
  36.       call :end
  37.     )
  38. )
  39. :end
  40. choice /t 1 /d y /n>nul
  41. goto ExecBat
复制代码

回复 1# licunwei

一楼代码用dir简报获取文件时间戳的精度是分钟级
还是用powershell功能获取秒级精度的文件时间戳更方便,只是powershell的首启速度较慢而已...
以下代码假设*603*.xml文件修改时间 ‘总是晚于’ *602*.xml文件修改时间
  1. @echo off &setlocal enabledelayedexpansion
  2. set "folder=D:\SCETC\dataXml\"
  3. :[Loop]
  4. (call :getSofF "%folder%*602.xml" f602 h602 s602)
  5. (call :getSofF "%folder%*603.xml" f603 h603 s603)
  6. if !s602! gtr !s603! set/a "s603+=(24+h603)*3600"
  7. set/a "dt=!s603!-!s602!"
  8. if !dt! gtr 1 (xcopy /y /i "!f603!" "D:\交易失败流水\%date:~0,4%%date:~5,2%%date:~8,2%\")
  9. goto[Loop]
  10. :getSofF
  11. for /f "tokens=1* delims=:" %%A in (' dir /b/o-d/tw "%~1"^|findstr /n ".*"^|findstr /lbc:"1:" ') do (
  12. for /f "delims=" %%t in (' powershell "(Get-ChildItem """%%B""").LastWriteTime" ') do (
  13. set "t=%%t" &for /f "tokens=1-3 delims=:" %%a in ("!t:~-8!") do for %%k in (%%a %%b %%c) do (
  14. set "k=%%k" &if "!k:~,1!"=="0" (set "ts=!ts!:!k:~-1!") else set "ts=!ts!:!k!"
  15. )
  16. )
  17. for /f "tokens=1-3 delims=:" %%a in ("!ts:~1!") do (set "%~3=%%a"&set/a "s=%%a*3600+%%b*60+%%c")
  18. set "%~2=%%B" &set "%~4=!s!"
  19. )
  20. exit/b
复制代码

TOP

回复 15# licunwei


你到powershell区去问下
因为是循环执行的,所以poweshell不要退出,一直用PS执行所有操作就可以

QQ 20147578

TOP

回复 9# czjt1234


   老师能否按你的思路帮我优化下,谢谢了。

TOP

回复 12# hfxiang


    谢谢  我试试。

TOP

回复 10# 77七


    好的 谢谢  我再测试观察看看。

TOP

回复 1# licunwei

12~15行提取时间方式
  1. for /F %%a in ('dir /b /s /o-d %folder%*602.xml') do (
  2.     set /a m+=1
  3.     set "timestamp_602!m!=%%~ta"
  4. )
复制代码
set "timestamp_602!m!=%%~ta"不含秒,建议用forfiles,可在命令行窗口中测试一下如下指令然后看能否用得上:
  1. FORFILES /p "D:\SCETC\dataXml" /S /M *60?.xml /C "cmd /c echo  @path @fdate @ftime"
复制代码
另:时间计算可参考
http://www.bathome.net/redirect. ... 37235&ptid=2627

TOP

回复 9# czjt1234


   是的,这是个问题,开始我也想过,频繁调用powershell效率会降低,很可能是刻舟求剑。写出来也是一种参考吧,如果不行,楼主再寻求他法。
bat小白,请多指教!谢谢!

TOP

回复 8# licunwei


  
找不到文件
这个是关键的报错信息。
4楼代码10-11行之间增加个判断
  1. if not defined file_%%x (
  2. echo file_%%x 文件不存在\其它原因,返回重试
  3. endlocal
  4. timeout 1
  5. goto :loop
  6. )
复制代码
1

评分人数

bat小白,请多指教!谢谢!

TOP

慢一点的电脑,批处理调用powershell可能都不止一秒
建议批处理第一行获取当前时间,后面再对时间进行处理

QQ 20147578

TOP

回复 4# 77七


    等待 0 秒,按一个键继续 ...

C:\Users\Administrator\Desktop>goto :loop

C:\Users\Administrator\Desktop>setlocal

C:\Users\Administrator\Desktop>for %x in (602 603) do (
for /F "delims=" %i in ('dir /b /s /a-d /od "C:\Users\Administrator\Desktop\新建文件夹\\*%x.xml"') do (set file_%x=%i )
setlocal enabledelayedexpansion
for /F "delims=" %a in ('powershell -Command "$time=(Get-Item '!file_%x!').LastWriteTime; $epoch = Get-Date '1970-01-01'; $span = New-TimeSpan -Start $epoch -End $time; $milliseconds = [math]::Round($span.TotalMilliseconds); Write-Output $milliseconds"') do (
endlocal
set "unix_%x=%a"
)
)

C:\Users\Administrator\Desktop>(
for /F "delims=" %i in ('dir /b /s /a-d /od "C:\Users\Administrator\Desktop\新建文件夹\\*602.xml"') do (set file_602=%i )
setlocal enabledelayedexpansion
for /F "delims=" %a in ('powershell -Command "$time=(Get-Item '!file_602!').LastWriteTime; $epoch = Get-Date '1970-01-01'; $span = New-TimeSpan -Start $epoch -End $time; $milliseconds = [math]::Round($span.TotalMilliseconds); Write-Output $milliseconds"') do (
endlocal
set "unix_602=%a"
)
)
找不到文件

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602=Get-Item : 无法将参数绑定到参数“Path”,因为该参数为空字符串。"
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602=所在位置 行:1 字符: 17"
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602=+ $time=(Get-Item '').LastWriteTime; $epoch = Get-Date '1970-01-01'; $s ..."
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602=+                 ~~"
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602=    + CategoryInfo          : InvalidData: ( [Get-Item],ParameterBindingValidationException"
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602=    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.GetI "
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602=   temCommand"
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602= "
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602=New-TimeSpan : 无法将参数“End”绑定到目标。设置“End”时发生异常:“无法将空值转换为类型“System.DateTime”。”"
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602=所在位置 行:1 字符: 108"
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602=+ ... e '1970-01-01'; $span = New-TimeSpan -Start $epoch -End $time; $milli ..."
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602=+                                                             ~~~~~"
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602=    + CategoryInfo          : WriteError: (:) [New-TimeSpan], ParameterBindingException"
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602=    + FullyQualifiedErrorId : ParameterBindingFailed,Microsoft.PowerShell.Commands.NewTimeSpanCommand"
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602= "
)

C:\Users\Administrator\Desktop>(
endlocal
set "unix_602=0"
)

C:\Users\Administrator\Desktop>(
for /F "delims=" %i in ('dir /b /s /a-d /od "C:\Users\Administrator\Desktop\新建文件夹\\*603.xml"') do (set file_603=%i )
setlocal enabledelayedexpansion
for /F "delims=" %a in ('powershell -Command "$time=(Get-Item '!file_603!').LastWriteTime; $epoch = Get-Date '1970-01-01'; $span = New-TimeSpan -Start $epoch -End $time; $milliseconds = [math]::Round($span.TotalMilliseconds); Write-Output $milliseconds"') do (
endlocal
set "unix_603=%a"
)
)

C:\Users\Administrator\Desktop>(set file_603=C:\Users\Administrator\Desktop\新建文件夹\S0003510010100101003020240523054215350603.xml )

C:\Users\Administrator\Desktop>(
endlocal
set "unix_603=1716442935719"
)

C:\Users\Administrator\Desktop>if "0" GEQ "1716442935719" (set d=0-1716442935719 )  else (set d=1716442935719-0 )

C:\Users\Administrator\Desktop>for /F %a in ('powershell -c "1716442935719-0"') do (
echo 毫秒差 %a
if %a GTR 200 (for /F %a in ('powershell -c "'{0:yyyyMMdd}' -f (get-date)"') do (
md "D:\交易失败流水\%a"  2>nul
copy "C:\Users\Administrator\Desktop\新建文件夹\S0003510010100101003020240523054215350603.xml" "D:\交易失败流水\%a"
del "C:\Users\Administrator\Desktop\新建文件夹\S0003510010100101003020240523054215350603.xml"
) )
)

C:\Users\Administrator\Desktop>(
echo 毫秒差 1716442935719
if 1716442935719 GTR 200 (for /F %a in ('powershell -c "'{0:yyyyMMdd}' -f (get-date)"') do (
md "D:\交易失败流水\1716442935719"  2>nul
copy "C:\Users\Administrator\Desktop\新建文件夹\S0003510010100101003020240523054215350603.xml" "D:\交易失败流水\1716442935719"
del "C:\Users\Administrator\Desktop\新建文件夹\S0003510010100101003020240523054215350603.xml"
) )
)
毫秒差 1716442935719

C:\Users\Administrator\Desktop>(
md "D:\交易失败流水\20240528"  2>nul
copy "C:\Users\Administrator\Desktop\新建文件夹\S0003510010100101003020240523054215350603.xml" "D:\交易失败流水\20240528"
del "C:\Users\Administrator\Desktop\新建文件夹\S0003510010100101003020240523054215350603.xml"
)
已复制         1 个文件。

C:\Users\Administrator\Desktop>endlocal

C:\Users\Administrator\Desktop>timeout 1

等待 0 秒,按一个键继续 ...

TOP

回复 4# 77七


    老师  还是会经常计算错误,下面是2个文件计算出来的毫秒差,157和171644293519   是同样的2个文件,157是对的,但偶尔会计算错误,误删除文件。

毫秒差 1716442935719
del "C:\Users\Administrator\Desktop\新建文件夹\S0003510010100101003020240523054215350603.xml"
毫秒差 157
毫秒差 157
毫秒差 157
毫秒差 157
毫秒差 157
毫秒差 157

TOP

回复 1# licunwei
  1. @echo off
  2. set "folder=D:\SCETC\dataXml\"
  3. cd /d "%folder%"
  4. for /f "delims=" %%a in ('dir /b /s /a-d /od *602.xml') do (
  5.     set "File602=%%a"
  6. )
  7. for /f "delims=" %%a in ('powershell –NoProfile –ExecutionPolicy Bypass "(Get-ChildItem '%File602%').LastWriteTime"') do (
  8.     set "Time602=%%a"
  9. )
  10. for /f "delims=" %%a in ('dir /b /s /a-d /od *603.xml') do (
  11.     set "File603=%%a"
  12. )
  13. for /f "delims=" %%a in ('powershell –NoProfile –ExecutionPolicy Bypass "(Get-ChildItem '%File603%').LastWriteTime"') do (
  14.     set "Time603=%%a"
  15. )
  16. if "%Time602%" == "%Time603%" (
  17.     echo copy %File603%
  18. ) else (
  19.     echo not copy
  20. )
  21. pause
复制代码
测试代码之前请做好备份

TOP

回复 4# 77七

谢谢,明天我试试。

TOP

回复 3# licunwei


   借助ai写了一条powershell命令,将文件修改时间转换为unix时间戳,精确到毫秒。
使用前先备份。
  1. @echo off
  2. set "folder=D:\SCETC\dataXml\"
  3. set "str=.LastWriteTime; $epoch = Get-Date '1970-01-01'; $span = New-TimeSpan -Start $epoch -End $time; $milliseconds = [math]::Round($span.TotalMilliseconds); Write-Output $milliseconds"
  4. :loop
  5. setlocal
  6. for %%x in (602 603) do (
  7. for /f "delims=" %%i in ('dir /b /s /a-d /od "%folder%\*%%x.xml"') do (
  8. set file_%%x=%%i
  9. )
  10. setlocal enabledelayedexpansion
  11. for /f "delims=" %%a in ('powershell -Command "$time=(Get-Item '!file_%%x!')%str%"') do (
  12. endlocal
  13. set "unix_%%x=%%a"
  14. )
  15. )
  16. if "%unix_602%" geq "%unix_603%" (
  17. set d=%unix_602%-%unix_603%
  18. ) else (
  19. set d=%unix_603%-%unix_602%
  20. )
  21. for /f %%a in ('powershell -c "%d%"') do (
  22. echo 毫秒差 %%a
  23. if %%a gtr 1000 (
  24. for /f %%a in ('powershell -c "'{0:yyyyMMdd}' -f (get-date)"') do (
  25. md "D:\交易失败流水\%%a" 2>nul
  26. copy "%file_603%" "D:\交易失败流水\%%a"
  27. del "%file_603%"
  28. )
  29. )
  30. )
  31. endlocal
  32. timeout 1
  33. goto :loop
复制代码
bat小白,请多指教!谢谢!

TOP

返回列表