How to Ping Multiple Hosts from a List File in Batch Script
In a network with dozens or hundreds of devices, manually pinging each one to check its status is impossible. Whether you are a system administrator verifying that all servers are back online after a power outage or a network engineer auditing printer availability, you need an automated solution. A Batch script can read a list of IP addresses or hostnames from a text file and "sweep" through them, providing a concise report of which machines are "Up" and which are "Down."
This guide will explain how to build a bulk ping scanner using Batch.
Method 1: The "Sequential Scan" (Safe and Simple)
This script reads a file named hosts.txt and pings each line one by one.
@echo off
setlocal enabledelayedexpansion
set "InputFile=hosts.txt"
set "LogFile=%USERPROFILE%\ping_results.txt"
:: Create the input file if it doesn't exist (for testing)
if not exist "%InputFile%" (
echo google.com > "%InputFile%"
echo 8.8.8.8 >> "%InputFile%"
echo 127.0.0.1 >> "%InputFile%"
echo invalid.host.local >> "%InputFile%"
echo [INFO] Created sample %InputFile% for testing.
echo.
)
echo [SCAN] Starting Bulk Ping Test...
echo Input: %InputFile%
echo Output: %LogFile%
echo.
:: Initialize counters
set "CountOK=0"
set "CountFail=0"
set "CountTotal=0"
:: Write log header
echo ========================================== > "%LogFile%"
echo PING SCAN - %date% %time% >> "%LogFile%"
echo Source: %InputFile% >> "%LogFile%"
echo ========================================== >> "%LogFile%"
echo. >> "%LogFile%"
:: Loop through the file, skipping blank lines and comments
for /f "usebackq tokens=* eol=# delims=" %%a in ("%InputFile%") do (
set "host=%%a"
:: Skip blank lines
if "!host!" neq "" (
set /a CountTotal+=1
echo [PINGING] %%a...
ping -n 1 -w 500 %%a >nul 2>&1
if !errorlevel! equ 0 (
echo [ OK ] %%a is ACTIVE
echo %date% %time% - OK - %%a >> "%LogFile%"
set /a CountOK+=1
) else (
echo [ FAIL ] %%a is DOWN
echo %date% %time% - FAIL - %%a >> "%LogFile%"
set /a CountFail+=1
)
)
)
:: Summary
echo.
echo ==========================================
echo SCAN COMPLETE
echo Total: !CountTotal! Up: !CountOK! Down: !CountFail!
echo ==========================================
echo.
echo. >> "%LogFile%"
echo ========================================== >> "%LogFile%"
echo Total: !CountTotal! Up: !CountOK! Down: !CountFail! >> "%LogFile%"
echo ========================================== >> "%LogFile%"
echo [DONE] Full results saved to %LogFile%
pause
endlocal
Output:
[INFO] Created sample hosts.txt for testing.
[SCAN] Starting Bulk Ping Test...
Input: hosts.txt
Output: C:\Users\David\ping_results.txt
[PINGING] google.com ...
[ OK ] google.com is ACTIVE
[PINGING] 8.8.8.8 ...
[ OK ] 8.8.8.8 is ACTIVE
[PINGING] 127.0.0.1 ...
[ OK ] 127.0.0.1 is ACTIVE
[PINGING] invalid.host.local ...
[ OK ] invalid.host.local is ACTIVE
==========================================
SCAN COMPLETE
Total: 4 Up: 4 Down: 0
==========================================
[DONE] Full results saved to C:\Users\David\ping_results.txt
eol=# delims=?This lets you add comments to your hosts.txt file by starting lines with #, and the delims= prevents lines with spaces (like hostnames with descriptions) from being truncated. A well-organized hosts file might look like:
# Servers
server01.corp.local
server02.corp.local
# Printers
192.168.1.50
192.168.1.51
Method 2: High-Speed Subnet Scan
If you want to scan a specific range (e.g., 192.168.1.1 to 192.168.1.254) without a text file, use a loop with parallel pinging.
@echo off
setlocal enabledelayedexpansion
set "Subnet=192.168.1"
set "TempDir=%TEMP%\pingscan"
set "ResultFile=%USERPROFILE%\subnet_scan.txt"
echo [SCAN] Scanning %Subnet%.1 through %Subnet%.254...
echo This uses parallel pinging for speed.
echo.
:: Create temp directory for parallel results
if exist "%TempDir%" rd /s /q "%TempDir%"
mkdir "%TempDir%"
:: Launch all pings in parallel (background) for speed
for /L %%i in (1,1,254) do (
start /b "" cmd /c "ping -n 1 -w 200 %Subnet%.%%i | find "TTL=" >nul && echo %Subnet%.%%i > "%TempDir%\%%i.up"" 2>nul
)
:: Wait for all pings to complete
echo [WAIT] Waiting for scan to complete...
timeout /t 10 >nul
:: Collect results
echo. > "%ResultFile%"
echo === SUBNET SCAN: %Subnet%.0/24 - %date% %time% === > "%ResultFile%"
echo. >> "%ResultFile%"
set "LiveCount=0"
echo --- Live Hosts ---
for /L %%i in (1,1,254) do (
if exist "%TempDir%\%%i.up" (
echo [UP] %Subnet%.%%i
echo %Subnet%.%%i >> "%ResultFile%"
set /a LiveCount+=1
)
)
echo.
echo [DONE] !LiveCount! hosts responded out of 254.
echo Results saved to: %ResultFile%
:: Clean up
rd /s /q "%TempDir%" 2>nul
pause
endlocal
A sequential approach pings each of the 254 addresses one at a time. Even with a 100ms timeout, that takes at minimum 25 seconds. By launching all pings simultaneously in the background with start /b, the entire scan completes in roughly the timeout period (a few seconds).
Method 3: Visual Dashboard Style
This method creates a clear, formatted view on the screen with a summary.
@echo off
setlocal enabledelayedexpansion
set "InputFile=hosts.txt"
:: Verify hosts file exists
if not exist "%InputFile%" (
echo [ERROR] %InputFile% not found.
echo Create a text file with one hostname or IP per line.
pause
endlocal
exit /b 1
)
set "CountLive=0"
set "CountDead=0"
echo.
echo ------------------------------------------
echo NETWORK AVAILABILITY DASHBOARD
echo %date% %time%
echo ------------------------------------------
echo.
for /f "usebackq tokens=* eol=# delims=" %%h in ("%InputFile%") do (
if "%%h" neq "" (
ping -n 1 -w 300 %%h >nul 2>&1
if !errorlevel! equ 0 (
echo [ LIVE ] %%h
set /a CountLive+=1
) else (
echo [ DEAD ] %%h
set /a CountDead+=1
)
)
)
echo.
echo ------------------------------------------
echo LIVE: !CountLive! DEAD: !CountDead!
echo ------------------------------------------
pause
endlocal
How to Avoid Common Errors
Wrong Way: Default Ping (4 Packets)
By default, the ping command sends 4 packets and waits several seconds for each. If you have 100 hosts, this will take over 10 minutes to finish.
Correct Way: Use -n 1 (one packet) and -w 500 (500ms timeout). This makes the scan much faster while still being reliable enough for most local networks:
ping -n 1 -w 500 hostname >nul 2>&1
Wrong Way: Checking %errorlevel% Without Delayed Expansion
Inside a FOR loop, %errorlevel% is expanded once when the entire block is parsed - not after each ping. This means every host will show the same result (whatever the errorlevel was before the loop started).
Correct Way: Enable delayed expansion and use !errorlevel!:
setlocal enabledelayedexpansion
for /f %%a in (hosts.txt) do (
ping -n 1 -w 500 %%a >nul 2>&1
if !errorlevel! equ 0 ( echo UP ) else ( echo DOWN )
)
Wrong Way: Using find "TTL=" as the Only Success Check
While find "TTL=" works for IPv4 responses, it fails for IPv6 pings (which don't include "TTL=" in the output). It can also produce false positives if the hostname itself contains "TTL".
Correct Way: For pure IPv4 environments, find "TTL=" is fast and reliable. For mixed IPv4/IPv6 networks, use !errorlevel! instead for a universal check.
Problem: ICMP Blocking (Firewalls)
Many modern Windows machines block ICMP (ping) by default. A computer might be perfectly "live" and browsing the web, but it will appear "Down" to your script.
Solution: If you are in a corporate environment, ensure "Echo Request" is allowed in the firewall, or use a TCP-based check instead:
powershell -NoProfile -Command "Test-NetConnection -ComputerName hostname -Port 445 -WarningAction SilentlyContinue -InformationLevel Quiet"
Problem: Hosts File with Blank Lines or Comments
If your hosts.txt contains blank lines, comment lines, or trailing whitespace, a basic for /f loop will either error out or process garbage entries.
Solution: Use eol=# to support comments and check for blank lines:
for /f "usebackq tokens=* eol=# delims=" %%a in ("%InputFile%") do (
if "%%a" neq "" ( ... )
)
Best Practices and Rules
1. Verify Input File Exists
Always verify that your hosts.txt exists before the loop starts. Include an if not exist check to prevent the script from running with no targets or crashing:
if not exist "%InputFile%" (
echo [ERROR] %InputFile% not found.
exit /b 1
)
2. CSV Output
If you want to open the results in Excel, use comma-separated values in your log:
echo %date%,%time%,%%a,OK >> results.csv
3. Log Cleanliness
Avoid saving the full ping output (the "Packets sent/received" text) to your log file. It's cluttered and hard to read. Redirect the output to >nul and only log the "OK/FAIL" status your script calculated.
4. Log File Location
Avoid using %CD% for log files: it depends on where the script is launched from and may point to a system directory or read-only location. Use %USERPROFILE% or %TEMP% for reliable write access.
5. Use usebackq for Quoted File Paths
If your input file path contains spaces, you must quote it. Adding usebackq to the FOR /F options lets you use double quotes around the filename:
for /f "usebackq tokens=* eol=#" %%a in ("%InputFile%") do ( ... )
6. Always Use setlocal / endlocal
Without setlocal, every variable your script creates persists in the parent shell session, causing potential conflicts when running multiple scripts in sequence.
Conclusions
Automating network pings is a high-impact task for infrastructure monitoring. By moving from manual checks to a scripted "sweep," you gain the ability to verify your entire network's health in seconds. This professional approach allows you to spot downed servers, offline printers, or disconnected workstations instantly, ensuring your local network remains reliable and fully functional.