# How to perform wildcard string comparison in batch file

My batch file writes a list of files on screen where it contains the .cs extension

for /F "usebackq delims=" %%A in (cleartool ls  -rec ^| find /V "Rule:" ^| find /V "hijacked" ^| find /V "eclipsed" ^| find /V "-->") do (
if "%%~xA"==".cs"  echo %%A
)


This works fine. I want to enhance the functionality by adding another condition. I want to remove a certain word if it exists in the phrase. The word is obj

Examples of my results are

myThing\obj\this.cs
obj\other\that\this.cs
debug\this\that.cs

I tried

for /F "usebackq delims=" %%A in (cleartool ls  -rec ^| find /V "Rule:" ^| find /V "hijacked" ^| find /V "eclipsed" ^| find /V "-->") do (
if "%%~xA"==".cs" if NOT "%%A"=="*obj*" echo %%A
)


but this doesn't change the results compared to the first.

I think my if syntax is correct, and the issue is actually with the "%%A"=="*obj*"

• The best suggestion would be to migrate this toward PowerShell. The syntax is much prettier and significantly more feature rich - which in the long run may benefit your updating and script functionality. I figured PS would be a joke like CMD, but it's actually pretty impressive. – nerdwaller Jan 31 '14 at 16:07

You were thinking correctly: the wildcards (*) are not supported.

A good workaround for the problem is findstr, though you need to retrieve result via %ERRORLEVEL% and I think you must cache it through another variable (so that next if does not override it's value):

echo %%A | findstr /C:"obj"
set obj_errorlevel=%errorlevel%

if "%%~xA"==".cs" if "%obj_errorlevel%"=="1" echo %%A


...but that is a hard way.

An even easier way is to add the condition to the source command (the one inside if) by adding another pipe stage: ^| find /V "obj":

for /F "usebackq delims=" %%A in (cleartool ls  -rec ^| find /V "Rule:" ^| find /V "hijacked" ^| find /V "eclipsed" ^| find /V "-->" ^| find /V "obj")


I believe your edit is correct, in that you can't use wildcards in the If string compare. It's actually looking for *obj*, including the asterisks.

Perhaps use FindStr instead, by piping any .cs matches through it. It returns an errorlevel of 0 if found, and 1 if not found.

Code example:

for /F "usebackq delims=" %%A in (cleartool ls  -rec ^| find /V "Rule:" ^| find /V "hijacked" ^| find /V "eclipsed" ^| find /V "-->") do (
if "%%~xA"==".cs" echo %%A | findstr /C:"obj" 1>nul & if errorlevel 1 echo %%A
)


I dont think you can use 2 if's like that. Try:

for    xxxxxxx   (
if first-condition (
if second-condition (
statement(s)
)
)
)

• This results in the same as my code sadly... I don't think the issue is with the IF statement, but reading if a string exists within a string.. – MyDaftQuestions Jan 31 '14 at 16:01
• Oddly enough you can use it the OP's way (but yours is much more legible). In any case, I think formatting is highly important and this is a much better solution to the multiple IF issue in cmd. – nerdwaller Jan 31 '14 at 16:06
• @nerdwaller It works without the quotes in Win7 and later (and in theory it should). But I distinctly remember having issues with this particular nested if construct on W2K, XP and W2k3. I could be wrong. It was quite a while ago. – Tonny Jan 31 '14 at 19:59
• People still use those!? Haha, in any case I voted you up since I always support clean code – nerdwaller Jan 31 '14 at 20:53

The asterisks are not interpreted as wildcards, so the condition evaluates to false. Instead of a second if-statement, you can use findstr to determine whether the variable contains the text 'obj'. The command sets %errorlevel% to zero if a match has been found, to zero otherwise.

A convenient way of using this value is through the conditional command seperators && and ||. A command appended with || will only be executed if the previous command returned a non-zero error level, e.g.:

(echo %%A | findstr /R .*obj.*)>NUL ||
if "%%~xA"==".cs" echo %%A


The addition of >NUL is important in this scenario. Without suppressing the output, both the first line and the second line could print the variable %%A. To avoid confusion, you'll want different cases to produce different results.

Of course, if you're already using findstr, you could get rid of the if-statement and its body altogether. The readability isn't great either way; the code below is provided as an alternative.

(echo %%A|findstr /R /V ".*obj.*")|findstr /R /C:"\.cs \$"


A solution that might work for what you want to do. This uses SET's string substitution, as explained at Rob van der Woude's site.

@echo off
set _myvar=this\has\obj\in the string
echo Original: %_myvar%
::replace the string obj in _myvar
set _myvar=%_myvar:obj=%
::replace any double back-slashes in _myvar
set _myvar=%_myvar:\\=\%
echo Withou obj: %_myvar%


_myvar originally contains the string 'obj' in it. The first time we remove the string using SET's string substitution. The second time, we remove any double-slashes that might be left over due to the location of 'obj'. After the colon, you have the string you want to look for in the variable. The string to replace with comes after the equal sign before the end of the substitution.

Hope that helps!

Try expanding the contents of yourfile.cs and replace word or letter with desired character either nothing or something. Here's my idea.

Drag .cs file on top of batch file icon to open with it so that .cs file is param 1

@echo off

setlocal EnableDelayedExpansion

set /p a= enter letter to change:
set /p b= enter letter to change to:
set /p file=<%1

for /f %%c in ("!file:~!") do (
set "code=!file:%a%=%b%!"
echo !code!>myfile.cs
)


Change myfile.cs to any name you want

Please improve my ans for better functions.