Check if files in a directory are still being written using Windows Batch Script

◇◆丶佛笑我妖孽 提交于 2019-12-11 19:16:23

问题


Here's my batch file to parse a directory, and zip files of certain type

 REM Begin ------------------------
    tasklist /FI "IMAGENAME eq 7za.exe" /FO CSV > search.log
    FOR /F %%A IN (search.log) DO IF %%~zA EQU 0 GOTO end
    for /f "delims=" %%A in ('dir C:\Temp\*.ps /b') do (
"C:\Program Files\7-Zip\cmdline\7za.exe" a -tzip -mx9 "C:\temp\Zip\%%A.zip" "C:\temp\%%A"
Move "C:\temp\%%A" "C:\Temp\Archive"
)
    :end
    del search.log
    REM pause
    exit
    REM End ---------------------------

This code works just fine for 90% of my needs. It will be deployed as a scheduled task.

However, the *.ps files are rather large (minimum of 1GB) in real time cases. So the code is supposed to check if the incoming file is completely written and is not locked by the application that is writing it.

I saw another example elsewhere, that suggested the following approach

:TestFile
ren c:\file.txt c:\file.txt
if errorlevel 0 goto docopy
sleep 5
goto TestFile
:docopy

However this example is good for a fixed file. How can I use that many labels and GoTo's inside a for loop without causing an infinite loop? Or is this code safe to be used in the For Loop?

Thank you for any help.


回答1:


I agree that the GOTO loop is risky--an error would make it loop forever, which is not good at all for a Scheduled Task.

For tasks like this, I tend to use the Resource Kit tool called Robocopy, in part because it's fast, but also because it's robust. I usually set it to do 3-5 retries (option /r:3) with a 10 second pause if the file is not ready (/w:10), and then have it log any errors so I can review them (/log:...). Very handy. Here's the full list of options, which can help you pick exactly what you need to copy.

I may have been a little hasty with my first response. The little rename trick could be integrated into your script and would probably work alright:

...
for /f "delims=" %%A in ('dir C:\Temp\*.ps /b') do (
:TestFile
ren C:\Temp\%%A.ps C:\Temp\%%A.ps
if errorlevel 0 goto Continue
sleep 5
goto TestFile
:Continue
"C:\Program Files\7-Zip\cmdline\7za.exe" a -tzip -mx9 "C:\temp\Zip\%%A.zip" "C:\temp\%%A"
move "C:\temp\%%A" "C:\Temp\Archive"
)
...

Or, if you wanted to use Robocopy, you could do the file move first then do the zipping. (As long as you're moving the file on the same partition--in your example it's from C:\TEMP to C:\TEMP\Archived--there's no lag.) This way Robocopy will the do waiting until the file is ready, then let your script go on with the zipping. Here's an example:

...
for /f "delims=" %%A in ('dir C:\Temp\*.ps /b') do (
robocopy C:\Temp C:\Temp\Archive\ %%A.ps /mov /r:100 /w:5 /log+:copylog.txt
"C:\Program Files\7-Zip\cmdline\7za.exe" a -tzip -mx9 "C:\temp\Archive\%%A.zip" "C:\temp\Archive\%%A.ps"
)
...



回答2:


The following is the batch file script I used eventually. It is working very well for the requirement. I hope it helps someone with the same requirement as mine.

tasklist /FI "IMAGENAME eq 7za.exe" /FO CSV > search.log
FOR /F %%%A IN (search.log) DO IF %%%~zA EQU 0 GOTO end
for /f "delims=" %%A in ('dir C:\Temp\ZIP\*.txt /b') do (
     :TestFile 
    "C:\Program Files\7-Zip\cmdline\7za.exe" a -tzip -mx9 "C:\temp\Zip\ZipDone%%A.zip" "C:\temp\zip\%%A"
     Move "C:\temp\ZIP\%%A" "C:\Temp\ZIP\Archive"
     )
:end
del search.log
REM pause
Exit


来源:https://stackoverflow.com/questions/2541853/check-if-files-in-a-directory-are-still-being-written-using-windows-batch-script

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!