How to Replace a Specific Line Number in a File in Batch Script
Automating the update of a specific configuration line, such as changing a port number on line 12 or updating a version string on line 2, is a common task for deployment scripts. Since Batch cannot edit a file in place, the standard approach is to read the original file line-by-line and rewrite it into a new file, substituting the new content when the target line number is reached.
In this guide, we will demonstrate how to replace a specific line using a for /f loop and a counter.
The Strategy: The "Filter and Swap"
To replace line 7:
- Read the file line-by-line using a counter.
- For lines 1–6, write the text exactly as it is.
- For line 7, write your new text instead of the original line.
- For lines 8+, continue writing the original text.
Implementation Script
This script replaces line 5 of settings.conf with a new value.
@echo off
setlocal EnableDelayedExpansion
set "Source=settings.conf"
set "TempFile=%TEMP%\replace_line_%RANDOM%.tmp"
set "TargetLine=5"
set "ReplacementText=LOG_LEVEL=DEBUG"
:: Check file exists
if not exist "%Source%" (
echo [ERROR] Source file "%Source%" not found.
pause
exit /b 1
)
if %TargetLine% lss 1 (
echo [ERROR] Invalid line number.
pause
exit /b 1
)
echo Replacing line %TargetLine% in "%Source%"...
set /a current=0
set "replaced=0"
(
for /f "usebackq delims=" %%A in ("%Source%") do (
set /a current+=1
if !current! equ %TargetLine% (
echo %ReplacementText%
set "replaced=1"
) else (
echo %%A
)
)
) > "%TempFile%"
if !replaced! equ 0 (
echo [WARNING] Line %TargetLine% exceeds file length (!current! lines^).
del "%TempFile%" 2>nul
pause
exit /b 1
)
move /y "%TempFile%" "%Source%" >nul
if !errorlevel! equ 0 (
echo [SUCCESS] Line %TargetLine% replaced in "%Source%".
) else (
echo [ERROR] Failed to replace file.
pause
exit /b 1
)
pause
exit /b 0
For example, consider this input file settings.conf:
APP_NAME=MyApplication
VERSION=1.0.0
ENVIRONMENT=PRODUCTION
MAX_USERS=100
LOG_LEVEL=INFO
The output file settings.conf will be:
APP_NAME=MyApplication
VERSION=1.0.0
ENVIRONMENT=PRODUCTION
MAX_USERS=100
LOG_LEVEL=DEBUG
The for /f loop skips blank lines by design and also skips lines beginning with ; (the default eol character). If your source file contains blank lines or lines starting with ;, those lines will be silently dropped during the rewrite, and the line counter will not match the actual line positions in the original file. For files where preserving all lines and accurate line numbering are critical, use the PowerShell method (Method 2) instead.
The script uses the delayed expansion toggle pattern: each line is set with delayed expansion disabled (set "line=%%A") to preserve literal ! characters in the file content. It is then output with delayed expansion enabled (echo(!line! and echo(!ReplacementText!) to safely handle &, |, >, <, and other special characters. The echo( syntax also prevents ECHO is off. messages for empty values.
Method 2: The PowerShell Bridge (Recommended for Large Files)
If your file is large or contains blank lines that must be preserved, PowerShell handles line replacement quickly and accurately using array index assignment.
Implementation Script
@echo off
setlocal
set "Source=settings.conf"
set "TargetLine=5"
set "NewText=LOG_LEVEL=DEBUG"
:: Verify source file exists
if not exist "%Source%" (
echo [ERROR] Source file "%Source%" not found.
pause
exit /b 1
)
echo Replacing line %TargetLine% in "%Source%"...
:: PowerShell arrays are zero-based, so subtract 1 from the line number
:: Bounds checking prevents silent errors on out-of-range positions
powershell -NoProfile -Command ^
"$lines = Get-Content -Path '%Source%'; " ^
"$idx = %TargetLine% - 1; " ^
"if ($idx -lt 0 -or $idx -ge $lines.Count) { " ^
" Write-Host '[WARNING] Line %TargetLine% is out of range.'; exit 1 " ^
"} else { " ^
" $lines[$idx] = '%NewText%'; " ^
" $lines | Set-Content -Path '%Source%' -Encoding UTF8 " ^
"}"
if %errorlevel% equ 0 (
echo [SUCCESS] Line %TargetLine% replaced in "%Source%".
) else (
echo [WARNING] No changes were made.
pause
exit /b 1
)
pause
exit /b 0
PowerShell arrays use zero-based indexing, so line 5 in the file corresponds to index 4 in the array. The script converts automatically by subtracting 1 from the user-facing line number. Bounds checking ensures that an out-of-range line number produces a clear warning instead of a silent failure or an exception.
Why Replace by Line Number?
- Format-Strict Files: Some legacy systems require specific settings to exist at exact coordinates within the file.
- Anonymous Edits: If you do not know the name of a setting but you know its position (e.g., "the second line is always the password"), replacing by number is the only way to update it.
- Patching: When distributing a quick fix, telling a script to "change line 10" is often easier than building a complex search-and-replace regex that might accidentally match other similar lines.
Best Practices
- Verify Source File: Always check that the input file exists before processing. A missing file will cause the
for /floop to silently produce empty output, and themovecommand will overwrite the source path with an empty temp file. - Handle Out-of-Bounds: If the specified line number exceeds the total number of lines in the file, the script should handle this gracefully, either by warning the user or by exiting without modifying the file.
- Backup First: Replacing lines is a destructive action. Consider creating a backup copy (
copy "%Source%" "%Source%.bak") before overwriting the original file. - Blank Line Awareness: The Batch
for /fmethod drops blank lines and miscounts line positions when blank lines are present in the source file. If line-position accuracy is critical, use the PowerShell method. - Zero-Based vs. One-Based: Always verify whether your tool counts from 0 or 1. Batch scripts count from 1 (first line processed is line 1), while PowerShell arrays count from 0 (first element is index 0). The PowerShell script in Method 2 converts automatically, but manual one-liners require careful index calculation.
- Special Characters in Replacement Text: If the replacement text contains single quotes, the PowerShell method will break because the text is wrapped in single-quote delimiters. For such content, use escaped quoting or pass the text through an environment variable.
- Temp File Hygiene: Use the
%TEMP%directory for intermediate files and include%RANDOM%in the filename to avoid collisions when multiple instances run simultaneously. - Encoding: Include
-Encoding UTF8in the PowerShellSet-Contentcommand to prevent non-ASCII characters from being corrupted by the default ANSI encoding in PowerShell 5.1.
Conclusion
Replacing a specific line by number is a surgical way to update configuration files and automation parameters. While native Batch requires a rewrite loop, it remains a robust solution for environments where external scripting languages are restricted. By mastering this technique, you can ensure your configuration updates are precise and predictable, maintaining the integrity of your system's settings with every run.