Skip to main content

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:

  1. Read the file line-by-line using a counter.
  2. For lines 1–6, write the text exactly as it is.
  3. For line 7, write your new text instead of the original line.
  4. 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:

settings.conf
APP_NAME=MyApplication
VERSION=1.0.0
ENVIRONMENT=PRODUCTION
MAX_USERS=100
LOG_LEVEL=INFO

The output file settings.conf will be:

settings.conf
APP_NAME=MyApplication
VERSION=1.0.0
ENVIRONMENT=PRODUCTION
MAX_USERS=100
LOG_LEVEL=DEBUG
warning

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.

tip

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.

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
info

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?

  1. Format-Strict Files: Some legacy systems require specific settings to exist at exact coordinates within the file.
  2. 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.
  3. 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

  1. Verify Source File: Always check that the input file exists before processing. A missing file will cause the for /f loop to silently produce empty output, and the move command will overwrite the source path with an empty temp file.
  2. 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.
  3. Backup First: Replacing lines is a destructive action. Consider creating a backup copy (copy "%Source%" "%Source%.bak") before overwriting the original file.
  4. Blank Line Awareness: The Batch for /f method 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.
  5. 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.
  6. 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.
  7. Temp File Hygiene: Use the %TEMP% directory for intermediate files and include %RANDOM% in the filename to avoid collisions when multiple instances run simultaneously.
  8. Encoding: Include -Encoding UTF8 in the PowerShell Set-Content command 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.