Skip to main content

How to Find the Position of a Substring in Batch Script

A common requirement in text processing is to find the starting position (or index) of a smaller string within a larger one. This is the equivalent of an IndexOf() or FIND() function in other programming languages. It's essential for parsing complex strings, extracting data that follows a known keyword, or validating a string's format. Windows Batch has no direct, built-in function for this task, so we must rely on a scripted workaround.

This guide will teach you the traditional "pure-batch" method, which uses a loop to search for the substring character by character. We will then cover the vastly simpler and more powerful modern approach using a PowerShell one-liner, which is the recommended method for its performance and flexibility.

The Challenge: No Native IndexOf() Function

The cmd.exe interpreter does not provide a simple command to get the index of a substring. We cannot do SET "pos=IndexOf(%MyString%, "fox")". This means we have to build the search logic ourselves. The native batch method involves iterating through the main string and checking for a match at each position.

The Core Method (Pure Batch): The Character-by-Character Loop

This method is entirely self-contained within the batch script but is also slow and complex.

The logic:

  1. Enable DelayedExpansion to work with variables inside a loop.
  2. Get the length of the substring we are searching for.
  3. Use a FOR /L loop to iterate through the main string, from the starting position 0 to the end.
  4. At each position in the loop, extract a piece of the main string that is the same length as our substring.
  5. Compare this extracted piece with our target substring.
  6. If they match, the current loop index is the position. Store it and exit the loop.

For any modern Windows system, a PowerShell one-liner is a far better solution. It uses the built-in .IndexOf() string method, which is highly optimized and easy to use.

Syntax: powershell -Command "('Main String').IndexOf('Substring')"

This command returns the zero-based index of the first occurrence of the substring.

Basic Example: Finding a Word in a Sentence

Let's find the starting position of the word "brown" in a sentence.

Method 1: Pure Batch Script

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

SET "MainString=The quick brown fox jumps over the lazy dog."
SET "SubString=brown"
SET "Position=-1"

REM Get the length of the substring
CALL :StrLen SubString SubLen

FOR /L %%i IN (0,1,256) DO (
IF !Position! EQU -1 (
SET "TempStr=!MainString:~%%i,%SubLen%!"
IF /I "!TempStr!"=="!SubString!" (
SET "Position=%%i"
)
)
)

ECHO Batch Method: The substring '%SubString%' starts at position %Position%.
GOTO :End

:StrLen
SET "string=!%1!" & SET "len=0"
:StrLenLoop
IF DEFINED string (SET "string=!string:~1!" & SET /A "len+=1" & GOTO :StrLenLoop)
SET "%2=%len%" & GOTO :EOF

:End
ENDLOCAL

Output:

Batch Method: The substring 'brown' starts at position 10.

Method 2: PowerShell Script

@ECHO OFF
SET "MainString=The quick brown fox jumps over the lazy dog."
SET "SubString=brown"
SET "Position=-1"

FOR /F %%P IN (
'powershell -Command "('%MainString%').IndexOf('%SubString%')"'
) DO (
SET "Position=%%P"
)

ECHO PowerShell Method: The substring '%SubString%' starts at position %Position%.

Output:

PowerShell Method: The substring 'brown' starts at position 10.
note

The position is 10 because strings are zero-indexed, meaning the first character is at position 0.

How the pure batch script works:

  • SETLOCAL ENABLEDELAYEDEXPANSION: Essential for using ! to get the current value of variables inside the loop.
  • :StrLen: A helper subroutine to calculate the length of the substring, as batch has no built-in length function.
  • FOR /L %%i IN (0,1,256) DO: A loop that counts from 0 to 256.
  • !MainString:~%%i,%SubLen%!: This is the key. At each step %%i, it extracts a substring of length %SubLen%. For example, at %%i=10, it extracts "brown".
  • IF /I "!TempStr!"=="!SubString!": It compares the extracted piece to our target. If they match, it sets the Position variable.

Common Pitfalls and How to Solve Them

Problem: The Substring is Not Found

What happens if the substring doesn't exist in the main string?

  • Pure Batch Method: The IF condition inside the loop is never met, so the Position variable remains at its initial "not found" value (we used -1).
  • PowerShell .IndexOf(): This method will directly return -1, which is the standard "not found" result in many programming languages.

This consistent behavior makes it easy to check for success: IF %Position% EQU -1 (ECHO Not found).

Problem: The Search is Case-Sensitive

By default, both methods are case-sensitive. They will not find "Brown" if the search term is "brown".

Solution:

  • Pure Batch: This is very difficult. You would first have to convert both the main string and the substring to lowercase, which is a very complex and slow operation in pure batch.
  • PowerShell (Recommended): This is incredibly easy. PowerShell's .IndexOf() method has an overload for handling case-insensitivity.
powershell -Command "('%MainString%').IndexOf('%SubString%', [System.StringComparison]::OrdinalIgnoreCase)"

This is a major advantage and a key reason why the PowerShell method is superior.

Practical Example: Parsing a Key from a "Key=Value" String

A common use for IndexOf is to parse data. This script finds the position of the = character and then extracts the substring that comes after it.

@ECHO OFF
SETLOCAL
SET "ConfigLine=ServerPort=8080"
SET "Delimiter=="
SET "Position=-1"
SET "Value="

REM --- Find the position of the delimiter ---
FOR /F %%P IN (
'powershell -Command "('%ConfigLine%').IndexOf('%Delimiter%')"'
) DO (
SET "Position=%%P"
)

IF %Position% EQU -1 (
ECHO Delimiter not found.
) ELSE (
ECHO Delimiter found at position %Position%.

REM --- Extract the value after the delimiter ---
SET /A "ValueStart=%Position% + 1"
CALL SET "Value=%%ConfigLine:~%ValueStart%%%

ECHO The extracted value is: %Value%
)
ENDLOCAL
note

The CALL SET with %% is a trick to perform a substring operation using a variable for the start position.

Conclusion

While you can find a substring's position using a pure batch script, the method is a complex demonstration of scripting gymnastics and is not practical for most uses.

  • The pure-batch loop method is slow, complex, and cannot easily handle case-insensitive searches.
  • The PowerShell .IndexOf() method is the overwhelmingly recommended best practice. It is significantly faster, more reliable, handles case-insensitivity with ease, and is much simpler to implement.

For any modern script that needs to find the position of a substring, the PowerShell one-liner is the professional and efficient choice.