Skip to content

How to Insert a Line at a Specific Line Number in a Batch Script

Learn how to insert text at a precise line number in a Batch script using for /f loops or PowerShell for accurate file editing, including handling edge cases like blank lines and special characters.

Injecting a new piece of data into an existing file, for example, adding a new DNS entry to a hosts file or inserting a configuration setting into the middle of an .ini file, is a complex task in Batch. Unlike a text editor, Batch cannot "open and edit" a specific line. Instead, we must read the original file line-by-line and rewrite it to a new file, inserting our new content when we reach the target line number.

In this guide, we will demonstrate how to perform this line injection using a for /f loop and a counter.

The Strategy: The Rewrite-and-Insert

To insert text at line 5:

  1. Initialize a counter to 0.
  2. Read the file line-by-line.
  3. For each line, increment the counter.
  4. If the counter equals 5, write the new text first, then the current line from the file.
  5. Otherwise, just write the current line from the file.

Implementation Script

This script inserts the line ## INSERTED HEADER ## at position 3 of a file.

@echo off
setlocal DisableDelayedExpansion

set "SourceFile=input.txt"
set "TempFile=%TEMP%\insert_temp_%RANDOM%.tmp"
set "InsertLine=3"
set "NewText=## INSERTED HEADER ##"

:: Verify source file exists
if not exist "%SourceFile%" (
    echo [ERROR] Source file "%SourceFile%" not found.
    pause
    exit /b 1
)

:: Validate that InsertLine is a positive integer
echo(%InsertLine%| findstr /r "^[1-9][0-9]*$" >nul || (
    echo [ERROR] Line number must be 1 or greater.
    pause
    exit /b 1
)

echo Inserting line at position %InsertLine% in "%SourceFile%"...

set "current=0"
set "inserted=0"

> "%TempFile%" (
    for /f "usebackq tokens=1* delims=:" %%N in (`findstr /n "^" "%SourceFile%"`) do (
        set "current=%%N"

        :: Insert BEFORE line %InsertLine%
        if %%N==%InsertLine% (
            <nul set /p "=%NewText%"
            echo(
            set "inserted=1"
        )

        :: Write original line, including blank lines
        <nul set /p "=%%O"
        echo(
    )
)

:: If requested line is beyond EOF, append at end
if "%inserted%"=="0" (
    echo [WARNING] Line %InsertLine% exceeds file length ^(%current% lines^).
    echo           Appending to end of file instead.
    >> "%TempFile%" <nul set /p "=%NewText%"
    >> "%TempFile%" echo(
)

:: Replace original with the new version
move /y "%TempFile%" "%SourceFile%" >nul

if errorlevel 1 (
    echo [ERROR] Failed to replace original file.
    pause
    exit /b 1
)

echo [SUCCESS] Line inserted at position %InsertLine%.
pause
exit /b 0

For large files or files that contain blank lines and special characters, PowerShell handles insertion with full accuracy.

Implementation Script

@echo off
setlocal

set "SourceFile=data.txt"
set "InsertLine=4"
set "NewText=NEW DATA LINE"

:: Verify source file exists
if not exist "%SourceFile%" (
    echo [ERROR] Source file "%SourceFile%" not found.
    pause
    exit /b 1
)

echo Inserting line at position %InsertLine% in "%SourceFile%"...

:: List.Insert uses a zero-based index, so subtract 1 from the line number
:: If the index exceeds the list length, the line is appended to the end
powershell -NoProfile -Command ^
    "$lines = [System.Collections.ArrayList]@(Get-Content -Path '%SourceFile%'); " ^
    "$idx = %InsertLine% - 1; " ^
    "if ($idx -ge $lines.Count) { $lines.Add('%NewText%') | Out-Null } " ^
    "else { $lines.Insert([Math]::Max(0, $idx), '%NewText%') }; " ^
    "$lines | Set-Content -Path '%SourceFile%' -Encoding UTF8"

if %errorlevel% equ 0 (
    echo [SUCCESS] Line inserted at position %InsertLine%.
) else (
    echo [ERROR] Insertion failed.
    pause
    exit /b 1
)
pause
exit /b 0

Why Insert by Line Number?

  1. Strict File Structures: Some legacy configuration files require metadata to be on specific lines (e.g., Line 1 is the title, Line 2 is the version).
  2. Code Patching: If you are automating a patch to another script, you may need to insert a CALL or a variable declaration at the top of the file without deleting existing code.
  3. Log Injection: Inserting a timestamp or a marker line into a log file to separate different execution runs.

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 missing 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 appending to the end or by warning the user.
  3. 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.
  4. Special Characters in Inserted Text: If the text you are inserting 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.
  5. Temp File Hygiene: Use the %TEMP% directory for intermediate files and include %RANDOM% in the filename to avoid collisions when multiple instances run simultaneously.
  6. Backup Strategy: Consider creating a backup of the original file before overwriting it with the modified version. If the insertion produces unexpected results, the backup provides a recovery path.

Conclusion

Inserting a line at a specific position is a complex task for a Batch script, but it is entirely possible with a structured rewrite loop. While PowerShell offers a faster, more accurate approach that preserves blank lines and handles special characters, the native Batch method remains a valuable zero-dependency solution for lightweight configuration patching. By mastering this technique, you can programmatically update complex files while preserving their existing structure.

Navigation