Skip to main content

How to Monitor a Folder for New Files in Batch Script

A common requirement in automation is to create a "drop folder" or "watch folder" where a script automatically processes any new files that appear. This is useful for tasks like automated data ingestion, converting files as they arrive, or kicking off a workflow when a specific trigger file is created. Windows Batch has no native, event-driven command to do this (like Linux's inotify), so we must build the logic ourselves using a polling loop.

This guide will teach you how to create a batch script that periodically scans a directory, compares its current state to a previous snapshot, and takes action when it discovers a new file. We will also cover the far superior and more efficient modern method using PowerShell, which is the recommended approach for any serious application.

The Challenge: No Native "Watch" Command

The main difficulty is that cmd.exe is not an event-driven environment. It cannot receive a notification from the operating system that "a new file was just created." Instead, our script must manually check the folder's contents over and over again. This process is called polling, and while it's less efficient than event-driven methods, it can be implemented effectively in a batch script.

The Core Method: A Polling Loop with a Snapshot

The logic for a polling script is as follows:

  1. Get an initial snapshot: On the first run, get a list of all files currently in the folder and store them in memory as the "already seen" list.
  2. Start an infinite loop:
  3. Inside the loop, get a fresh list of the files currently in the folder.
  4. For each file in the fresh list, check if it's in our "already seen" list.
  5. If a file is not in the "already seen" list, it's a new file. Process it, and then add it to the "already seen" list.
  6. Pause: Wait for a few seconds to avoid consuming excessive CPU.
  7. Repeat the loop.

The Script (Pure Batch): Monitoring for New Files

This script implements the polling logic. It uses an "associative array" trick (where variables are named after the files) to keep track of seen files.

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

REM --- Configuration ---
SET "MONITOR_FOLDER=C:\MyDropFolder"
SET "WAIT_SECONDS=5"

ECHO --- Starting Folder Monitor ---
ECHO Monitoring folder: "%MONITOR_FOLDER%"
ECHO Press Ctrl+C to stop.
ECHO.

REM --- Step 1: Get the initial snapshot of files ---
ECHO Creating initial snapshot of existing files...
FOR %%F IN ("%MONITOR_FOLDER%\*") DO (
SET "seen[%%~nxF]=1"
)
ECHO Initial scan complete. Monitoring for new files...
ECHO.

:MonitorLoop
REM --- Step 2: Get a fresh list and compare ---
FOR %%F IN ("%MONITOR_FOLDER%\*") DO (
REM Check if the file's "seen" variable is defined.
IF NOT DEFINED seen[%%~nxF] (
ECHO [%TIME%] New file detected: "%%~nxF"

REM --- (YOUR PROCESSING LOGIC GOES HERE) ---

REM Mark this file as "seen" for the next loop.
SET "seen[%%~nxF]=1"
)
)

REM --- Step 3: Pause before the next check ---
TIMEOUT /T %WAIT_SECONDS% /NOBREAK > NUL

GOTO :MonitorLoop

How the batch script works:

  • SETLOCAL ENABLEDELAYEDEXPANSION: Essential for this script, as the seen[] variables are being defined and checked within the same loop.
  • Initial Snapshot: The first FOR loop runs once. It populates our "database" of seen files by creating a variable for each one (e.g., SET "seen[report.txt]=1").
  • :MonitorLoop: This is the start of our infinite loop.
  • Main FOR Loop: This loop gets the current list of files in every iteration.
  • IF NOT DEFINED seen[%%~nxF]: This is the core logic. It checks if a variable named seen[filename] exists. If it doesn't, the file must be new.
  • Processing and Marking: Inside the IF block, we first announce the new file, then immediately SET the seen[] variable so it won't be detected as new in the next iteration.
  • TIMEOUT /T %WAIT_SECONDS%: This is a critical line that pauses the script, preventing it from running constantly and using 100% of a CPU core.

The pure-batch polling method works, but it is inefficient. The professional and vastly superior solution is to use PowerShell's FileSystemWatcher. This is an event-driven object that gets a notification directly from the operating system when a change occurs. It uses virtually zero CPU while waiting.

You can save this as a .ps1 file and run it.

Watch-Folder.ps1
### PowerShell Script: Watch-Folder.ps1 ###
$folderToWatch = "C:\MyDropFolder"
$filter = "*.*" # Watch for all file types

$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $folderToWatch
$watcher.Filter = $filter
$watcher.NotifyFilter = [System.IO.NotifyFilters]::FileName

Write-Host "Monitoring $folderToWatch for new files. Press Ctrl+C to stop."

# Define the action to take when a file is created
$action = {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
Write-Host "New file detected: $name at path $path"
# --- (YOUR PROCESSING LOGIC GOES HERE) ---
}

# Register the "Created" event
Register-ObjectEvent $watcher "Created" -Action $action

# Loop indefinitely to keep the script running
while ($true) { Start-Sleep -Seconds 10 }

This PowerShell script is the robust, production-ready solution for this task.

Common Pitfalls and How to Solve Them

Problem: The Loop Consumes 100% CPU

If you forget the TIMEOUT command in the batch script, the :MonitorLoop will run as fast as possible, consuming an entire CPU core.

Solution: Never create a polling loop without a pause. The TIMEOUT /T 5 /NOBREAK > NUL command is the modern and correct way to add a non-interactive pause to a script.

Problem: The Script Detects its Own Log File

If your processing logic involves creating a file (like a log) inside the same folder being monitored, the script will detect its own output file as a "new" file in the next iteration, potentially causing an infinite loop.

Solution: Always have your script write its output files to a different directory than the one it is monitoring.

Practical Example: An Automated "To-Process" Folder

This script uses the batch method to watch an "Input" folder. When a new file appears, it moves it to a "Processed" folder.

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "INPUT_FOLDER=%~dp0Input"
SET "PROCESSED_FOLDER=%~dp0Processed"
MKDIR "%INPUT_FOLDER%" 2>NUL
MKDIR "%PROCESSED_FOLDER%" 2>NUL

REM --- Initial Snapshot ---
FOR %%F IN ("%INPUT_FOLDER%\*") DO SET "seen[%%~nxF]=1"
ECHO Monitoring "%INPUT_FOLDER%"...

:MonitorLoop
FOR %%F IN ("%INPUT_FOLDER%\*") DO (
IF NOT DEFINED seen[%%~nxF] (
ECHO [%TIME%] New file detected: "%%~nxF". Moving to Processed folder.
MOVE "%%F" "%PROCESSED_FOLDER%\"
SET "seen[%%~nxF]=1"
)
)
TIMEOUT /T 5 /NOBREAK > NUL
GOTO :MonitorLoop

Conclusion

Monitoring a folder for new files is a powerful automation technique.

  • The pure-batch polling loop is a functional solution that demonstrates advanced scripting logic. It is suitable for simple or non-critical tasks but is inherently inefficient.
  • The PowerShell FileSystemWatcher is the modern, professional, and highly recommended method. It is event-driven, efficient, and robust.

For any production or critical system, using the PowerShell approach is the superior choice for its performance and reliability.