How do you get the string length in a batch file?

WindowsStringBatch File

Windows Problem Overview


There doesn't appear to be an easy way to get the length of a string in a batch file. E.g.,

SET MY_STRING=abcdefg
SET /A MY_STRING_LEN=???

How would I find the string length of MY_STRING?

Bonus points if the string length function handles all possible characters in strings including escape characters, like this: !%^^()^!.

Windows Solutions


Solution 1 - Windows

As there is no built in function for string length, you can write your own function like this one:

@echo off
setlocal
REM *** Some tests, to check the functionality ***
REM *** An emptyStr has the length 0
set "emptyString="
call :strlen result emptyString
echo %result%

REM *** This string has the length 14
set "myString=abcdef!%%^^()^!"
call :strlen result myString
echo %result%

REM *** This string has the maximum length of 8191
setlocal EnableDelayedExpansion
set "long=."
FOR /L %%n in (1 1 13) DO set "long=!long:~-4000!!long:~-4000!"
(set^ longString=!long!!long:~-191!)

call :strlen result longString
echo %result%

goto :eof

REM ********* function *****************************
:strlen <resultVar> <stringVar>
(   
    setlocal EnableDelayedExpansion
    (set^ tmp=!%~2!)
	if defined tmp (
		set "len=1"
		for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
			if "!tmp:~%%P,1!" NEQ "" ( 
				set /a "len+=%%P"
				set "tmp=!tmp:~%%P!"
			)
		)
	) ELSE (
		set len=0
	)
)
( 
    endlocal
    set "%~1=%len%"
    exit /b
)

This function needs always 13 loops, instead of a simple strlen function which needs strlen-loops.
It handles all characters.

The strange expression (set^ tmp=!%~2!) is necessary to handle ultra long strings, else it's not possible to copy them.

Solution 2 - Windows

You can do it in two lines, fully in a batch file, by writing the string to a file and then getting the length of the file. You just have to subtract two bytes to account for the automatic CR+LF added to the end.

Let's say your string is in a variable called strvar:

ECHO %strvar%> tempfile.txt
FOR %%? IN (tempfile.txt) DO ( SET /A strlength=%%~z? - 2 )

The length of the string is now in a variable called strlength.

In slightly more detail:

  • FOR %%? IN (filename) DO ( ... : gets info about a file
  • SET /A [variable]=[expression] : evaluate the expression numerically
  • %%~z? : Special expression to get the length of the file

To mash the whole command in one line:

ECHO %strvar%>x&FOR %%? IN (x) DO SET /A strlength=%%~z? - 2&del x

Solution 3 - Windows

I prefer jeb's accepted answer - it is the fastest known solution and the one I use in my own scripts. (Actually there are a few additional optimizations bandied about on DosTips, but I don't think they are worth it)

But it is fun to come up with new efficient algorithms. Here is a new algorithm that uses the FINDSTR /O option:

@echo off
setlocal
set "test=Hello world!"

:: Echo the length of TEST
call :strLen test

:: Store the length of TEST in LEN
call :strLen test len
echo len=%len%
exit /b

:strLen  strVar  [rtnVar]
setlocal disableDelayedExpansion
set len=0
if defined %~1 for /f "delims=:" %%N in (
  '"(cmd /v:on /c echo(!%~1!&echo()|findstr /o ^^"'
) do set /a "len=%%N-3"
endlocal & if "%~2" neq "" (set %~2=%len%) else echo %len%
exit /b

The code subtracts 3 because the parser juggles the command and adds a space before CMD /V /C executes it. It can be prevented by using (echo(!%~1!^^^).


For those that want the absolute fastest performance possible, jeb's answer can be adopted for use as a batch "macro" with arguments. This is an advanced batch technique devloped over at DosTips that eliminates the inherently slow process of CALLing a :subroutine. You can get more background on the concepts behind batch macros here, but that link uses a more primitive, less desirable syntax.

Below is an optimized @strLen macro, with examples showing differences between the macro and :subroutine usage, as well as differences in performance.

@echo off
setlocal disableDelayedExpansion

:: -------- Begin macro definitions ----------
set ^"LF=^
%= This creates a variable containing a single linefeed (0x0A) character =%
^"
:: Define %\n% to effectively issue a newline with line continuation
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

:: @strLen  StrVar  [RtnVar]
::
::   Computes the length of string in variable StrVar
::   and stores the result in variable RtnVar.
::   If RtnVar is is not specified, then prints the length to stdout.
::
set @strLen=for %%. in (1 2) do if %%.==2 (%\n%
  for /f "tokens=1,2 delims=, " %%1 in ("!argv!") do ( endlocal%\n%
    set "s=A!%%~1!"%\n%
    set "len=0"%\n%
    for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (%\n%
      if "!s:~%%P,1!" neq "" (%\n%
        set /a "len+=%%P"%\n%
        set "s=!s:~%%P!"%\n%
      )%\n%
    )%\n%
    for %%V in (!len!) do endlocal^&if "%%~2" neq "" (set "%%~2=%%V") else echo %%V%\n%
  )%\n%
) else setlocal enableDelayedExpansion^&setlocal^&set argv=,

:: -------- End macro definitions ----------

:: Print out definition of macro
set @strLen

:: Demonstrate usage

set "testString=this has a length of 23"

echo(
echo Testing %%@strLen%% testString
%@strLen% testString

echo(
echo Testing call :strLen testString
call :strLen testString

echo(
echo Testing %%@strLen%% testString rtn
set "rtn="
%@strLen% testString rtn
echo rtn=%rtn%

echo(
echo Testing call :strLen testString rtn
set "rtn="
call :strLen testString rtn
echo rtn=%rtn%

echo(
echo Measuring %%@strLen%% time:
set "t0=%time%"
for /l %%N in (1 1 1000) do %@strlen% testString testLength
set "t1=%time%"
call :printTime

echo(
echo Measuring CALL :strLen time:
set "t0=%time%"
for /l %%N in (1 1 1000) do call :strLen testString testLength
set "t1=%time%"
call :printTime
exit /b


:strlen  StrVar  [RtnVar]
::
:: Computes the length of string in variable StrVar
:: and stores the result in variable RtnVar.
:: If RtnVar is is not specified, then prints the length to stdout.
::
(
  setlocal EnableDelayedExpansion
  set "s=A!%~1!"
  set "len=0"
  for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
    if "!s:~%%P,1!" neq "" (
      set /a "len+=%%P"
      set "s=!s:~%%P!"
    )
  )
)
(
  endlocal
  if "%~2" equ "" (echo %len%) else set "%~2=%len%"
  exit /b
)

:printTime
setlocal
for /f "tokens=1-4 delims=:.," %%a in ("%t0: =0%") do set /a "t0=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100
for /f "tokens=1-4 delims=:.," %%a in ("%t1: =0%") do set /a "t1=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100
set /a tm=t1-t0
if %tm% lss 0 set /a tm+=24*60*60*100
echo %tm:~0,-2%.%tm:~-2% msec
exit /b

-- Sample Output --

@strLen=for %. in (1 2) do if %.==2 (
  for /f "tokens=1,2 delims=, " %1 in ("!argv!") do ( endlocal
    set "s=A!%~1!"
    set "len=0"
    for %P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
      if "!s:~%P,1!" neq "" (
        set /a "len+=%P"
        set "s=!s:~%P!"
      )
    )
    for %V in (!len!) do endlocal&if "%~2" neq "" (set "%~2=%V") else echo %V
  )
) else setlocal enableDelayedExpansion&setlocal&set argv=,

Testing %@strLen% testString
23

Testing call :strLen testString
23

Testing %@strLen% testString rtn
rtn=23

Testing call :strLen testString rtn
rtn=23

Measuring %@strLen% time:
1.93 msec

Measuring CALL :strLen time:
7.08 msec

Solution 4 - Windows

The first few lines are simply to demonstrate the :strLen function.

@echo off
set "strToMeasure=This is a string"
call :strLen strToMeasure strlen
echo.String is %strlen% characters long
exit /b

:strLen
setlocal enabledelayedexpansion
:strLen_Loop
  if not "!%1:~%len%!"=="" set /A len+=1 & goto :strLen_Loop
(endlocal & set %2=%len%)
goto :eof

Of course, this is not quite as efficient at the "13 loop" version provided by jeb. But it is easier to understand, and your 3GHz computer can slip through a few thousand iterations in a small fraction of a second.

Solution 5 - Windows

Just found ULTIMATE solution:

set "MYSTRING=abcdef!%%^^()^!"
(echo "%MYSTRING%" & echo.) | findstr /O . | more +1 | (set /P RESULT= & call exit /B %%RESULT%%)
set /A STRLENGTH=%ERRORLEVEL%-5
echo string "%MYSTRING%" length = %STRLENGTH%

The output is:

string "abcdef!%^^()^!" length = 14

It handles escape characters, an order of magnitude simpler then most solutions above, and contains no loops, magic numbers, DelayedExpansion, temp files, etc.

In case usage outside batch script (mean putting commands to console manually), replace %%RESULT%% key with %RESULT%.

If needed, %ERRORLEVEL% variable could be set to FALSE using any NOP command, e.g. echo. >nul

Solution 6 - Windows

Yes, of course there's an easy way, using vbscript (or powershell).

WScript.Echo Len( WScript.Arguments(0) )

save this as strlen.vbs and on command line

c:\test> cscript //nologo strlen.vbs "abcd"

Use a for loop to capture the result ( or use vbscript entirely for your scripting task)

Certainly beats having to create cumbersome workarounds using batch and there's no excuse not to use it since vbscript is available with each Windows distribution ( and powershell in later).

Solution 7 - Windows

If you are on Windows Vista +, then try this Powershell method:

For /F %%L in ('Powershell $Env:MY_STRING.Length') do (
	Set MY_STRING_LEN=%%L
)

or alternatively:

Powershell $Env:MY_STRING.Length > %Temp%\TmpFile.txt
Set /p MY_STRING_LEN = < %Temp%\TmpFile.txt
Del %Temp%\TmpFile.txt

I'm on Windows 7 x64 and this is working for me.

Solution 8 - Windows

I like the two line approach of jmh_gr.

It won't work with single digit numbers unless you put () around the portion of the command before the redirect. since 1> is a special command "Echo is On" will be redirected to the file.

This example should take care of single digit numbers but not the other special characters such as < that may be in the string.

(ECHO %strvar%)> tempfile.txt

Solution 9 - Windows

If you insist on having this trivial function in pure batch I suggest this:

@echo off

set x=somestring
set n=0
set m=255

:loop
if "!x:~%m%,1!" == "" (
	set /a "m>>=1"
	goto loop
) else (
	set /a n+=%m%+1
	set x=!x:~%m%!
	set x=!x:~1!
	if not "!x!" == "" goto loop
)

echo %n%

PS. You must have delayed variable expansion enabled to run this.

EDIT. Now I have made an improved version:

@echo off

set x=somestring
set n=0

for %%m in (4095 2047 1023 511 255 127 63 31 15 7 3 1 0) do (
	if not "!x:~%%m,1!" == "" (
		set /a n+=%%m+1
		set x=!x:~%%m!
		set x=!x:~1!
		if "!x!" == "" goto done
	)
)

:done
echo %n%

EDIT2. If you have a C compiler or something on your system you can create the programs you need and miss on the fly if they don't exist. This method is very general. Take string length as an example:

@echo off

set x=somestring

if exist strlen.exe goto comp
echo #include "string.h" > strlen.c
echo int main(int argc, char* argv[]) { return strlen(argv[1]); } >> strlen.c
CL strlen.c 

:comp
strlen "%x%"
set n=%errorlevel%
echo %n%

You have to set up PATH, INCLUDE and LIB appropriately. This too can be done on the fly from the batch script. Even if you don't know whether you've got a compiler or don't know where it is you can search for it in your script.

Solution 10 - Windows

Just another batch script to calculate the length of a string, in just a few lines. It may not be the fastest, but it's pretty small. The subroutine ":len" returns the length in the second parameter. The first parameter is the actual string being analysed. Please note - special characters must be escaped, that is the case with any string in the batch file.

@echo off
setlocal
call :len "Sample text" a
echo The string has %a% characters.
endlocal
goto :eof

:len <string> <length_variable> - note: string must be quoted because it may have spaces
setlocal enabledelayedexpansion&set l=0&set str=%~1
:len_loop
set x=!str:~%l%,1!&if not defined x (endlocal&set "%~2=%l%"&goto :eof)
set /a l=%l%+1&goto :len_loop

Solution 11 - Windows

@echo off & setlocal EnableDelayedExpansion
set Var=finding the length of strings
for /l %%A in (0,1,10000) do if not "%Var%"=="!Var:~0,%%A!" (set /a Length+=1) else (echo !Length! & pause & exit /b)

set the var to whatever you want to find the length of it or change it to set /p var= so that the user inputs it. Putting this here for future reference.

Solution 12 - Windows

I made this simple function to find the length of string

for /l %%a in (0,1,10000) do if not "!text:~%%a,1!" == "" set/a text_len=!text_len!+1

You need to make sure that both !text! and !text_len! variables are defined first

Solution 13 - Windows

@echo off
::   warning doesn't like * ( in mystring

setlocal enabledelayedexpansion 

set mystring=this is my string to be counted forty one

call :getsize %mystring%
echo count=%count% of "%mystring%" 

set mystring=this is my string to be counted

call :getsize %mystring%

echo count=%count% of "%mystring%" 

set mystring=this is my string
call :getsize %mystring%

echo count=%count% of "%mystring%" 
echo.
pause
goto :eof

:: Get length of mystring line ######### subroutine getsize ########

:getsize

set count=0

for /l %%n in (0,1,2000) do (

    set chars=

    set chars=!mystring:~%%n!

    if defined chars set /a count+=1
)
goto :eof

:: ############## end of subroutine getsize ########################

Solution 14 - Windows

I want to preface this by saying I don't know much about writing code/script/etc. but thought I'd share a solution I seem to have come up with. Most of the responses here kinda went over my head, so I was curious to know if what I've written is comparable.

@echo off

set stringLength=0

call:stringEater "It counts most characters"
echo %stringLength%
echo.&pause&goto:eof

:stringEater
set var=%~1
:subString
set n=%var:~0,1%
if "%n%"=="" (
        goto:eof
    ) else if "%n%"==" " (
        set /a stringLength=%stringLength%+1
    ) else (
        set /a stringLength=%stringLength%+1
    )
set var=%var:~1,1000%
if "%var%"=="" (
        goto:eof
    ) else (
        goto subString
    )

goto:eof

Solution 15 - Windows

It's Much Simplier!

Pure batch solution. No temp files. No long scripts.

@echo off
setlocal enabledelayedexpansion
set String=abcde12345

for /L %%x in (1,1,1000) do ( if "!String:~%%x!"=="" set Lenght=%%x & goto Result )

:Result 
echo Lenght: !Lenght!

1000 is the maximum estimated string lenght. Change it based on your needs.

Solution 16 - Windows

I know its a little late - like 10 years, but what I do for this is to write a C# Console app called strlen call it and then use the errorlevel to get the returned length

Solution 17 - Windows

@ECHO OFF

SET string=
SET /A stringLength=0

:CheckNextLetter
REM Subtract the first letter and count up until the string="".
IF "%string%" NEQ "" (
	SET string=%string:~1%
	SET /A stringLength=%stringLength%+1
	GOTO :CheckNextLetter
) ELSE (
	GOTO :TheEnd
)

:TheEnd
	ECHO There is %stringLength% character^(s^) in the string.
PAUSE

This works for me. Hope this is useful for someone else. No need to adjust for any length. I just remove the first letter and compare against "" until the string equals "".

Solution 18 - Windows

You can try this code. Fast, you can also include special characters

@echo off
set "str=[string]"
echo %str% > "%tmp%\STR"
for %%P in ("%TMP%\STR") do (set /a strlen=%%~zP-3)
echo String lenght: %strlen%

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionindivView Question on Stackoverflow
Solution 1 - WindowsjebView Answer on Stackoverflow
Solution 2 - WindowsJoshua HonigView Answer on Stackoverflow
Solution 3 - WindowsdbenhamView Answer on Stackoverflow
Solution 4 - WindowsCody BarnesView Answer on Stackoverflow
Solution 5 - WindowsAlex ShevchenkoView Answer on Stackoverflow
Solution 6 - Windowsghostdog74View Answer on Stackoverflow
Solution 7 - WindowsFarrukh WaheedView Answer on Stackoverflow
Solution 8 - WindowsOnlineOverHereView Answer on Stackoverflow
Solution 9 - WindowsHenrik4View Answer on Stackoverflow
Solution 10 - WindowsSilkwormView Answer on Stackoverflow
Solution 11 - WindowsunpredictublView Answer on Stackoverflow
Solution 12 - WindowsDarwishView Answer on Stackoverflow
Solution 13 - Windowseddie Duncan-DunlopView Answer on Stackoverflow
Solution 14 - WindowsJohnView Answer on Stackoverflow
Solution 15 - Windowsuser10744194View Answer on Stackoverflow
Solution 16 - WindowsTerry WattsView Answer on Stackoverflow
Solution 17 - WindowsRick SanchezView Answer on Stackoverflow
Solution 18 - WindowsAnic17View Answer on Stackoverflow