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?
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
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 ?
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. |
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. |
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. |
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
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