Rob van der Woude's Scripting Pages

Batch How To ...

Convert strings to upper or lower case

PATH

Back in the MS-DOS epoch, the value of the PATH variable used to be all upper case, at least when set using the PATH command.
In order to use this feature on another string, you had to save the PATH to another temporary variable, then use the PATH command to save the string to be converted in the PATH variable, copy the value of the PATH variable back to the original variable, and restore the PATH variable.

Though the PATH command in Windows NT 4 and later no longer converts to upper case, we can still use this feature by calling COMMAND.COM:

@ECHO OFF
IF "%1"=="/C" GOTO COMMAND
COMMAND /C %~s0 /C %*
GOTO:EOF

:COMMAND
PATH %2
ECHO.%PATH%

This code may be compact, but to use the result in a variable would require additional code:

@ECHO OFF
IF "%1"=="/C" GOTO COMMAND
FOR /F "tokens=*" %%A IN ('COMMAND /C %~s0 /C %*') DO SET UpCase=%%A
GOTO:EOF

:COMMAND
PATH %2
ECHO.%PATH%

Still compact, but if you have to do some maintenace on this code, say, 3 years from now, will you still understand what it does? At first sight?

SET, Take One

Personally, I prefer using the string substitution feature of Windows' SET command, combined with delayed variable expansion.
Besides conversion to upper case, this can be used just as easily to convert to lower case:

SETLOCAL ENABLEDELAYEDEXPANSION
SET String=Abc
SET String
CALL :UpCase String
SET String
CALL :LoCase String
SET String
ENDLOCAL
GOTO:EOF

:LoCase
:: Subroutine to convert a variable VALUE to all lower case.
:: The argument for this subroutine is the variable NAME.
SET %~1=!%~1:A=a!
SET %~1=!%~1:B=b!
SET %~1=!%~1:C=c!
SET %~1=!%~1:D=d!
SET %~1=!%~1:E=e!
SET %~1=!%~1:F=f!
SET %~1=!%~1:G=g!
SET %~1=!%~1:H=h!
SET %~1=!%~1:I=i!
SET %~1=!%~1:J=j!
SET %~1=!%~1:K=k!
SET %~1=!%~1:L=l!
SET %~1=!%~1:M=m!
SET %~1=!%~1:N=n!
SET %~1=!%~1:O=o!
SET %~1=!%~1:P=p!
SET %~1=!%~1:Q=q!
SET %~1=!%~1:R=r!
SET %~1=!%~1:S=s!
SET %~1=!%~1:T=t!
SET %~1=!%~1:U=u!
SET %~1=!%~1:V=v!
SET %~1=!%~1:W=w!
SET %~1=!%~1:X=x!
SET %~1=!%~1:Y=y!
SET %~1=!%~1:Z=z!
GOTO:EOF

:UpCase
:: Subroutine to convert a variable VALUE to all upper case.
:: The argument for this subroutine is the variable NAME.
SET %~1=!%~1:a=A!
SET %~1=!%~1:b=B!
SET %~1=!%~1:c=C!
SET %~1=!%~1:d=D!
SET %~1=!%~1:e=E!
SET %~1=!%~1:f=F!
SET %~1=!%~1:g=G!
SET %~1=!%~1:h=H!
SET %~1=!%~1:i=I!
SET %~1=!%~1:j=J!
SET %~1=!%~1:k=K!
SET %~1=!%~1:l=L!
SET %~1=!%~1:m=M!
SET %~1=!%~1:n=N!
SET %~1=!%~1:o=O!
SET %~1=!%~1:p=P!
SET %~1=!%~1:q=Q!
SET %~1=!%~1:r=R!
SET %~1=!%~1:s=S!
SET %~1=!%~1:t=T!
SET %~1=!%~1:u=U!
SET %~1=!%~1:v=V!
SET %~1=!%~1:w=W!
SET %~1=!%~1:x=X!
SET %~1=!%~1:y=Y!
SET %~1=!%~1:z=Z!
GOTO:EOF

The code is not quite as compact as the code that uses the PATH command, but it is much easier to read and maintain.

When run, the result of this sample batch code will look like this:

String=Abc
String=ABC
String=abc

SET, Take Two

Jiri sent me a clever adaptation of the UpCase and LoCase routines, plus what he calls a Title Case routine, also known as capitalization.
His code doesn't require delayed variable expansion, but unless you have a huge screen it does require some scrolling to read it... 😉

@ECHO OFF
SET String=Hello, how are you ?
SET String
CALL :TCase String
SET String
CALL :UpCase String
SET String
CALL :LoCase String
SET String
GOTO:EOF

:LoCase
:: Subroutine to convert a variable VALUE to all lower case.
:: The argument for this subroutine is the variable NAME.
FOR %%i IN ("A=a" "B=b" "C=c" "D=d" "E=e" "F=f" "G=g" "H=h" "I=i" "J=j" "K=k" "L=l" "M=m" "N=n" "O=o" "P=p" "Q=q" "R=r" "S=s" "T=t" "U=u" "V=v" "W=w" "X=x" "Y=y" "Z=z") DO CALL SET "%1=%%%1:%%~i%%"
GOTO:EOF

:UpCase
:: Subroutine to convert a variable VALUE to all UPPER CASE.
:: The argument for this subroutine is the variable NAME.
FOR %%i IN ("a=A" "b=B" "c=C" "d=D" "e=E" "f=F" "g=G" "h=H" "i=I" "j=J" "k=K" "l=L" "m=M" "n=N" "o=O" "p=P" "q=Q" "r=R" "s=S" "t=T" "u=U" "v=V" "w=W" "x=X" "y=Y" "z=Z") DO CALL SET "%1=%%%1:%%~i%%"
GOTO:EOF

:TCase
:: Subroutine to convert a variable VALUE to Title Case.
:: The argument for this subroutine is the variable NAME.
FOR %%i IN (" a= A" " b= B" " c= C" " d= D" " e= E" " f= F" " g= G" " h= H" " i= I" " j= J" " k= K" " l= L" " m= M" " n= N" " o= O" " p= P" " q= Q" " r= R" " s= S" " t= T" " u= U" " v= V" " w= W" " x= X" " y= Y" " z= Z") DO CALL SET "%1=%%%1:%%~i%%"
GOTO:EOF

This is what the result will look like:

String=Hello, how are you ?
String=Hello, How Are You ?
String=HELLO, HOW ARE YOU ?
String=hello, how are you ?

SET, Take Three

Brian Williams sent me a script by Brad Thone, which uses a hitherto unknown feature of XP's SET command: string substitution is case-insensitive.
The (slightly modified) script is shown below:

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

SET _SAMPLE=Test Output to be Cased.

CALL :UCase _SAMPLE _RESULTS
ECHO.%_RESULTS%

CALL :LCase _SAMPLE _RESULTS
ECHO.%_RESULTS%

ENDLOCAL
GOTO:EOF


:LCase
:UCase
:: Converts to upper/lower case variable contents
:: Syntax: CALL :UCase _VAR1 _VAR2
:: Syntax: CALL :LCase _VAR1 _VAR2
:: _VAR1 = Variable NAME whose VALUE is to be converted to upper/lower case
:: _VAR2 = NAME of variable to hold the converted value
:: Note: Use variable NAMES in the CALL, not values (pass "by reference")

SET _UCase=A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
SET _LCase=a b c d e f g h i j k l m n o p q r s t u v w x y z
SET _Lib_UCase_Tmp=!%1!
IF /I "%0"==":UCase" SET _Abet=%_UCase%
IF /I "%0"==":LCase" SET _Abet=%_LCase%
FOR %%Z IN (%_Abet%) DO SET _Lib_UCase_Tmp=!_Lib_UCase_Tmp:%%Z=%%Z!
SET %2=%_Lib_UCase_Tmp%
GOTO:EOF

The resulting output looks like this:

TEST OUTPUT TO BE CASED.
test output to be cased.

 

Warning: The SET commands on this page are vulnerable to code insertion exploits.
If you intend to use any of these techniques, make sure you understand the risks, and know how to prevent them.

FIND

A completely different approach, by Mark Tattersall, uses the fact that FIND returns "file names" in upper case in its "File not found" message:

FOR /F "usebackq tokens=2 delims=-" %%A IN (`"FIND "" "lower case text" 2>&1"`) DO ECHO THIS IS NOT%%A

or, simplified (provided the text does not contain single quotes):

FOR /F "tokens=2 delims=-" %%A IN ('FIND "" "lower case text" 2ˆ>ˆ&1') DO ECHO THIS IS NOT%%A

This can be used to convert text to upper case only, there is no lower case equivalent (yet).
Replacing the hard coded sample text by a command line argument we get something like this:

FOR /F "tokens=2 delims=-" %%A IN ('FIND "" "%~1" 2ˆ>ˆ&1') DO SET UpCaseText=%%A

Additional code is required to remove the trailing space that is introduced by this method.

Notes: (1) This method works with non-ASCII characters too.
  (2) This method requires Windows XP or later.

DIR

Another unexpected approach, also by Mark Tattersall, uses DIR /L to convert strings to lower case:

FOR %%B IN ("LOWER CaSe") DO (
	FOR /F "delims=~" %%A IN ('ECHO %%Bˆ> ~%%B ˆ& DIR /L /B ~%%B') DO (
		ECHO this is in %%A
		DEL /Q ~%%B
	)
)

This can be used to convert text to lower case only, there is no upper case equivalent (yet).
Replacing the hard coded sample text by a command line argument we get something like this:

FOR %%B IN ("%~1") DO (
	FOR /F "delims=~" %%A IN ('ECHO %%Bˆ> ~%%B ˆ& DIR /L /B ~%%B') DO (
		SET LoCaseText=%%A
		DEL /Q ~%%B
	)
)
Notes: (1) Write access to the current directory is required to create the temporary file.
  (2) The string must conform to all file name limitations.
  (3) The code as shown here does not check if the temporary file exists, so you may need some additonal code to prevent accidental file deletion.

Use other scripting languages

PowerShell

David Sacker sent me the following technique to convert strings to upper or lower case:

FOR /F "usebackq tokens=*" %%A IN (`powershell.exe -Command "('%*').ToUpper( )"`) DO SET UpCase=%%A
FOR /F "usebackq tokens=*" %%A IN (`powershell.exe -Command "('%*').ToLower( )"`) DO SET LoCase=%%A

Rexx

David's trick with PowerShell's -Command argument reminded me of RexxTry, native in OS/2 Rexx, and available as Rexx script in Open Object Rexx:

FOR /F "tokens=*" %%A IN ('rexxtry say translate^("%*"^) ^| FIND /I "%*"') DO SET UpCase=%%A

page last modified: 2022-10-22; loaded in 0.0015 seconds