'Check if file is locked inside a batch file for loop

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"
)



Solution 1:[1]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1