What is the best way to do a substring in a batch file?
Asked Answered
M

4

230

I want to get the name of the currently running batch file without the file extension.

Thanks to this link, I have the file name with the extension... but what is the best way to do a substring in a batch file?

Or is there another way to get the file name w/o the extension?

It is safe to assume 3 letter extensions in this scenario.

Morningglory answered 11/3, 2009 at 21:8 Comment(0)
O
453

Well, for just getting the filename of your batch the easiest way would be to just use %~n0.

@echo %~n0

will output the name (without the extension) of the currently running batch file (unless executed in a subroutine called by call). The complete list of such “special” substitutions for path names can be found with help for, at the very end of the help:

In addition, substitution of FOR variable references has been enhanced. You can now use the following optional syntax:

%~I         - expands %I removing any surrounding quotes (")
%~fI        - expands %I to a fully qualified path name
%~dI        - expands %I to a drive letter only
%~pI        - expands %I to a path only
%~nI        - expands %I to a file name only
%~xI        - expands %I to a file extension only
%~sI        - expanded path contains short names only
%~aI        - expands %I to file attributes of file
%~tI        - expands %I to date/time of file
%~zI        - expands %I to size of file
%~$PATH:I   - searches the directories listed in the PATH
               environment variable and expands %I to the
               fully qualified name of the first one found.
               If the environment variable name is not
               defined or the file is not found by the
               search, then this modifier expands to the
               empty string

The modifiers can be combined to get compound results:

%~dpI       - expands %I to a drive letter and path only
%~nxI       - expands %I to a file name and extension only
%~fsI       - expands %I to a full path name with short names only

To precisely answer your question, however: Substrings are done using the :~start,length notation:

%var:~10,5%

will extract 5 characters from position 10 in the environment variable %var%.

NOTE: The index of the strings is zero based, so the first character is at position 0, the second at 1, etc.

To get substrings of argument variables such as %0, %1, etc. you have to assign them to a normal environment variable using set first:

:: Does not work:
@echo %1:~10,5

:: Assign argument to local variable first:
set var=%1
@echo %var:~10,5%

The syntax is even more powerful:

  • %var:~-7% extracts the last 7 characters from %var%
  • %var:~0,-4% would extract all characters except the last four which would also rid you of the file extension (assuming three characters after the period [.]).

See help set for details on that syntax.

Obstruent answered 11/3, 2009 at 21:11 Comment(9)
Substring extraction doesn't work with FOR loop variables either so you'll have to do as follows (\r\n in the code mean line breaks because SO seem not allowing line breaks in comments): setlocal ENABLEDELAYEDEXPANSION \r\n for /f %%s in ('set') do ( \r\n set tmp=%%s \r\n echo !tmp:~-3! \r\n )Stegodon
@Stegodon why do you have to do this for FOR loops?Artima
@Adrian why not? FOR is a cornerstone construction in batch files performing pretty huge number of various tasks. Btw, there's one more way to cope with the task by using a subroutine, i.e. for /f %%s in ('set') do call :DoSmth "%%s" \r\n ... \r\n :DoSmth \r\n set var=%1 \r\n echo %var:~1,3%Stegodon
@Phate01, don't use %date% to construct a date in a certain format. The format is specific to the user's culture and may change. Use WMI instead to get date and time in a useful format that doesn't depend on the user's settings. Also I'm not sure what this comment is doing here, as this question was not about date or time.Obstruent
Actually you're right as I guess I wanted to comment a different question :)Off
%var is base 0 this is implicitly only :( derived from the second sample.Bellda
@Stegodon It does work, yes, but you have to use setlocal and enable delayed expansion.Wappes
@Wappes isn't that what I said in comment from Apr 28 '14 ?Stegodon
How to use ~othervar in place of ~10? It doesn't work for me.Nellynelms
S
43

Nicely explained above!

For all those who may suffer like me to get this working in a localized Windows (mine is XP in Slovak), you may try to replace the % with a !

So:

SET TEXT=Hello World
SET SUBSTRING=!TEXT:~3,5!
ECHO !SUBSTRING!
Scandium answered 3/2, 2012 at 7:51 Comment(3)
Note this will work only after setlocal ENABLEDELAYEDEXPANSION commandStegodon
try SET TEXT="<Hello World>" , SET SUBSTRING=!TEXT:~1,-1! or SET SUBSTRING=%TEXT:~1,-1% , ECHO !SUBSTRING! or ECHO %SUBSTRING%Woolson
How to use ~othervar in place of ~3? It doesn't work for me.Nellynelms
M
14

As an additional info to Joey's answer, which isn't described in the help of set /? nor for /?.

%~0 expands to the name of the own batch, exactly as it was typed.
So if you start your batch it will be expanded as

%~0   - mYbAtCh
%~n0  - mybatch
%~nx0 - mybatch.bat

But there is one exception, expanding in a subroutine could fail

echo main- %~0
call :myFunction
exit /b

:myFunction
echo func - %~0
echo func - %~n0
exit /b

This results to

main - myBatch
Func - :myFunction
func - mybatch

In a function %~0 expands always to the name of the function, not of the batch file.
But if you use at least one modifier it will show the filename again!

Mastoid answered 18/6, 2012 at 6:46 Comment(0)
V
1

How to do a substring within a batch file?
This version takes the start end length of the string as variables.
So it enables you to do a substring dynamically (e. g. in Loops).

@echo off
set sLongString=MyVeryLongString
call :Substring %sLongString% 2 8 sSubStrResult
echo %sSubStrResult%

Output: VeryLong

And here comes the necessary function:

REM ### Substring(sLongString, iStart, iCharCount): sSubStrResult
REM ### =========================================================
REM ### Example:
REM ###   set sLongString=MyVeryLongString
REM ###   call :Substring %sLongString% 2 8 sSubStrResult
REM ###   echo %sSubStrResult%
REM ### Output: VeryLong
REM ### Michael Hutter / Dez 2023
:Substring
SET sLongStr=%1
SET iFirstChar=%2
SET iCharCount=%3
CALL SET sSubStr=%%sLongStr:~%iFirstChar%,%iCharCount%%%
(endlocal & set %4=%sSubStr%)
goto :eof
Varityper answered 6/12, 2023 at 11:14 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.