How to Wait for a File to Exist Before Continuing in Batch Script
In automation, scripts often depend on each other. One script might need to process a file that is being generated by another application, a download, or a report-building tool. If your script tries to access this file before it has been created, it will fail with a "File Not Found" error. To build robust and resilient automation, you need a way to make your script pause and wait until the required file is available.
This guide will teach you how to create a simple and effective polling loop in your batch script to wait for a file. You will learn how to build a basic loop, how to improve it to prevent high CPU usage, and how to add a timeout to stop the script from waiting forever.
The Core Method: The IF EXIST Polling Loop
The standard way to wait for a file is to create a polling loop. This is a section of code that repeatedly checks for a condition: in this case, the existence of a file. The logic is straightforward:
- Define a label to mark the start of the loop.
- Use an
IF EXISTstatement to check if the file is present. - If the file exists, the condition is met, and the script can exit the loop and continue.
- If the file does not exist, use a
GOTOcommand to jump back to the starting label and check again.
Basic Example: A Simple Waiting Loop
This is the most elementary form of a polling loop. It works, but it has a significant flaw.
@ECHO OFF
SET "TARGET_FILE=C:\Downloads\report.csv"
ECHO Waiting for file: %TARGET_FILE%
:CheckForFile
IF EXIST "%TARGET_FILE%" GOTO :FileFound
REM If the file isn't found, loop back immediately.
GOTO :CheckForFile
:FileFound
ECHO.
ECHO [SUCCESS] File has been found!
ECHO Now proceeding with the rest of the script...
This script will lock up and wait, constantly checking for the file. Once you create report.csv in the C:\Downloads folder, the script will immediately detect it and continue.
Improving the Loop: Preventing High CPU Usage
The basic loop in the previous example is a "tight loop." It runs as fast as the processor will allow, consuming 100% of a CPU core while it waits. This is extremely inefficient and can slow down the entire system, potentially even delaying the creation of the very file it's waiting for.
The solution is to add a pause inside the loop. The modern, built-in command for this is TIMEOUT.
The following script is a script with a pause:
@ECHO OFF
SET "TARGET_FILE=C:\Downloads\report.csv"
ECHO Waiting for file: %TARGET_FILE%
:CheckForFile
IF EXIST "%TARGET_FILE%" GOTO :FileFound
ECHO File not found. Waiting 5 seconds before checking again...
REM Pause for 5 seconds, suppress keyboard input, and hide output.
TIMEOUT /T 5 /NOBREAK > NUL
GOTO :CheckForFile
:FileFound
ECHO.
ECHO [SUCCESS] File has been found!
This version is far more efficient. It checks for the file, and if it's not there, it sleeps for 5 seconds before trying again, using almost no CPU during the pause.
Making it Robust: Adding a Timeout Counter
What happens if the file never appears? The script will wait forever. A robust script should have a failure condition, i.e. a maximum amount of time it's willing to wait before giving up. We can achieve this by adding a counter to our loop.
For example, the following script has a counter and it will try a maximum of 12 times (waiting 5 seconds each time) for a total wait of about 60 seconds.
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "TARGET_FILE=C:\Downloads\report.csv"
SET "MAX_ATTEMPTS=12"
SET "WAIT_SECONDS=5"
SET "attempts=0"
ECHO Waiting for file: %TARGET_FILE%
:CheckForFile
IF EXIST "%TARGET_FILE%" GOTO :FileFound
SET /A "attempts+=1"
IF !attempts! GTR %MAX_ATTEMPTS% (
ECHO.
ECHO [ERROR] Timeout reached. The file was not found after %MAX_ATTEMPTS% attempts.
GOTO :EOF
)
ECHO File not found. Attempt !attempts! of %MAX_ATTEMPTS%. Waiting %WAIT_SECONDS% seconds...
TIMEOUT /T %WAIT_SECONDS% /NOBREAK > NUL
GOTO :CheckForFile
:FileFound
ECHO.
ECHO [SUCCESS] File has been found!
SETLOCAL ENABLEDELAYEDEXPANSION is required because the attempts variable is being changed and read inside the same loop.
Common Pitfalls and How to Solve Them
Problem: The Loop Never Ends
This is the most critical pitfall of any waiting loop. If the external process that's supposed to create the file fails silently, your script will be stuck indefinitely.
Solution: Always implement a timeout mechanism. A counter that limits the number of retries is the most reliable way to ensure your script will eventually terminate, either in success or failure.
Practical Example: Waiting for a Report to be Generated
This script simulates a real-world scenario. It first runs a command to generate a report (which we assume runs in the background and takes time), then it waits for the output file to appear before archiving it.
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "REPORT_GENERATOR=generate_report.exe"
SET "OUTPUT_FILE=C:\Reports\daily_sales.xlsx"
SET "ARCHIVE_DIR=C:\Reports\Archive"
SET "MAX_WAIT_MINUTES=5"
SET /A "MAX_ATTEMPTS=%MAX_WAIT_MINUTES% * 12"
ECHO --- Daily Report Archiver ---
ECHO.
ECHO Starting the report generator...
REM The START command runs the program without waiting for it to finish.
START "" "%REPORT_GENERATOR%"
ECHO Waiting for "%OUTPUT_FILE%" (max %MAX_WAIT_MINUTES% minutes)...
SET "attempts=0"
:WaitForReport
IF EXIST "%OUTPUT_FILE%" GOTO :ReportFound
SET /A "attempts+=1"
IF !attempts! GTR %MAX_ATTEMPTS% GOTO :ReportTimeout
REM Wait for 5 seconds
TIMEOUT /T 5 /NOBREAK > NUL
GOTO :WaitForReport
:ReportFound
ECHO [SUCCESS] Report found.
ECHO Archiving report...
MOVE "%OUTPUT_FILE%" "%ARCHIVE_DIR\"
GOTO :End
:ReportTimeout
ECHO [ERROR] Timed out waiting for the report file. Please check the generator.
:End
ENDLOCAL
Conclusion
Waiting for a file is a fundamental technique for creating interactive and resilient batch scripts. The IF EXIST polling loop is the standard method for achieving this.
For any production-ready script, remember these essential rules:
- Always include a pause in your loop, preferably with the
TIMEOUTcommand, to prevent high CPU usage. - Always include a timeout counter to ensure your script will eventually exit, even if the file never appears.
- Use
SETLOCAL ENABLEDELAYEDEXPANSIONwhen you use a counter that changes within the loop.
By building your loops with these principles, you can write automation that works harmoniously with other processes without causing system slowdowns or getting stuck.