Reputation: 1232
I have a script that runs through some files and copies them to another location. But the script needs to wait until the file is no longer being written to. I tried all the solutions here:
But the problem is that they don't work when wrapped in a loop. It always says the file is locked. If the script it cancelled and re-run it correctly finds the file unlocked. Am I doing something wrong or is there a trick to make this work?
For locking a test file, checkfile.txt
, I do:
(
>&2 pause
) >> checkfile.txt
Then the example script to check the file is this:
@echo off
for %%i in (*.txt) do (
:loop
ping localhost -n 5 > nul
echo "check if locked"
powershell -Command "$FileStream = [System.IO.File]::Open('%%i', 'Open', 'Write'); $FileStream.Close(); $FileStream.Dispose()" >NUL 2>NUL || (goto :loop)
echo "NOT locked anymore"
)
Upvotes: 0
Views: 1047
Reputation: 13
the following will have batch wait for a file to complete being written to:
:_WriteDelay TIMEOUT /T 60 > NUL
( (CALL ) >> < full path to file>) 2>NUL || GOTO _WriteDelay
Upvotes: 0
Reputation:
You cannot goto
in a loop as it will simply break the for
loop entirely. Additionally, the exit code
or errorlevel
is set for the last successful command. In this case being the powershell
dispose command. Simply do the loop outside of the code block:
@echo off & setlocal
for %%i in (*.txt) do call :loop %%~i
goto :EOF
:loop
powershell -Command "[System.IO.File]::Open('%1', 'Open', 'Write')">nul 2>&1 && echo %1 not locked || (
echo %1 Locked
("%systemroot%\system32\timeout.exe" /t 3)>nul
goto :loop
)
Note, the conditional operators (and &&
) and (or ||
) helps to evaluate the exit code without needing to do if
and else
statements.
Edit:
@echo off
for %%i in (*.txt) do (
setlocal enabledelayedexpansion
powershell -Command "[System.IO.File]::Open('%%~i', 'Open', 'Write')">nul 2>&1 && echo %%~i not locked || (
echo %%~i Locked
("%systemroot%\system32\timeout.exe" /t 3)>nul
endlocal
)
)
Upvotes: 1