I know from call /?, the ~ in variable (e.g. %~d1) is used to parse a part of file-path (driver here), but the tilde is used in another context here: https://www.tutorialspoint.com/batch_script/batch_script_string_length.htm:

@echo off
set str = Hello World
call :strLen str strlen
echo String is %strlen% characters long
exit /b

setlocal enabledelayedexpansion

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

Here, what is the meaning of this variable expansion: "!%1:~%len%!"? And how does it calculate the length of string via comparing it to empty string? What is the purpose of tilde here? Moreover, this example will get me into infinite loop where the output is if not "!str:~136!" == "" set /A len+=1 & goto :strLen_Loop (where the number !str:~n grows).

  • In this context, it is used to perform substring modification of a variable using an offset from the first character in the variables content, as explained in the help output of Set /?.
    – T3RR0R
    Jul 16, 2020 at 16:40

3 Answers 3


The tilde (~) sign is used in different ways in batch files:

  • Argument quote removal. A tilde sign before an command-line argument (such as "%~1") indicates to remove the surrounding quotes from the parameter. Such if the value for %1 is "Hi" then %~1 will expand to only Hi.

  • Substring processing. There is a way to extract substring from a string variable in batch file. The syntax is: %variable:~num_chars_skip,num_chars_keep%. Num chars skip means the point where to start in the string, or to exclude how much characters preceding the string variable. And num chars to keep indicates the number of characters after the start point. Num chars to keep is optional, but first is mandatory. If num chars to keep is not specified, only that num chars to keep'th character will be parsed.

You should read these in command prompt for more help:

  • call /?
  • for /?
  • set /?

Hope that helps

  • 1
    You can use a tilde with FOR metavariables, e.g. if %%A is "egg" then %%~A will be egg. Jul 16, 2020 at 19:23
  • 1
    You can remove quotes from %var% variables FOR %%A in (%quotedv%) do set unquotedv=%%~A Jul 16, 2020 at 20:27
  • OK, but why does the batch from tutorial causes me an infinite loop? Should not stop the strLen_Loop once the %1 input arg is empty? Why does it still process (in my example 136, and more)?
    – Herdsman
    Jul 16, 2020 at 21:52
  • Thanks @MichaelHarvey for information.
    – Wasif
    Jul 17, 2020 at 0:29
  • @Herdsman the loop is not infinite. Look at the If statement, whenever it matches, then the loop is exited.
    – Wasif
    Jul 17, 2020 at 0:30
  • For "fix" this tutorial code and prevent your loop infinite, quoted in the commentary:

I see, but yet, in my machine I need to ^C to terminate it. Just look how big number I get - 136 - even though there is no length or word with 136 characters - @Herdsman

@echo off && setlocal enabledelayedexpansion

set "_str=Hello World" & call :strLen_Loop str

if "%~1" == "" ( 
      endlocal & goto :EOF
    ) else if not "!_%~1:~%_len%!" == "" (
      set /A "_len+=1" & goto=:strLen_Loop
    ) else echo\String is !_len! characters long & exit /b

Try set /?:

Environment variable substitution has been enhanced as follows:


would expand the PATH environment variable, substituting each occurrence of "str1" in the expanded result with "str2". "str2" can be the empty string to effectively delete all occurrences of "str1" from the expanded output. "str1" can begin with an asterisk, in which case it will match everything from the beginning of the expanded output to the first occurrence of the remaining portion of str1.

May also specify substrings for an expansion.


would expand the PATH environment variable, and then use only the 5 characters that begin at the 11th (offset 10) character of the expanded result. If the length is not specified, then it defaults to the remainder of the variable value. If either number (offset or length) is negative, then the number used is the length of the environment variable value added to the offset or length specified.


would extract the last 10 characters of the PATH variable.


would extract all but the last 2 characters of the PATH variable.

The behavior is very useful, but the description about negative numbers is both confusing and inaccurate. It is correct for the first number (the offset): %VAR:~N% starts at the end minus N characters. When using a negative number for the second number, it is no longer the substring length, but interpreted as how many characters to stop before the end of the value, irrespective of its length. So %VAR:~1,-1% gives the value except the first and last characters, and both %VAR:~-2,-1% and %VAR:~-2,1% give the next to last character.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.