Batch file: Find if substring is in string (not in a file) Part 2 - Using Variables - string

In a Windows batch file, I have a string 'abcdefg'. I want to check if 'bcd' is in the string, but I also want each to be in a variable, or pass in a parameter for the string.
This solution comes close, but uses constants rather than variables.
Batch file: Find if substring is in string (not in a file)

try one:
set "var=abcdefg"
set "search=bcd"
CALL set "test=%%var:%search%=%%"
if "%test%"=="%var%" (echo %search% is not in %var%) else echo %search% in %var% found
set "var=abcdefg"
set "search=bcd"
echo %var%|findstr /lic:"%search%" >nul && echo %search% found || echo %search% not found

The solution is to use FindStr and the NULL redirect, >nul.
SET var=%1
SET searchVal=Tomcat
SET var|FINDSTR /b "var="|FINDSTR /i %searchVal% >nul
IF ERRORLEVEL 1 (echo It does't contain Tomcat) ELSE (echo It contains Tomcat)
Save as test.bat and execute with the parameter to be searched, as follows: test Tomcat7
C:\>test Tomcat9
It contains Tomcat

Related

String Substitution Using Variables in a FOR loop Batch Syntax

I am trying to use string substitution to truncate a list of full file paths down to relative paths in an existing text file. In addition there is some basic automated renaming. The renaming works as intended but the string substitution I cannot get to work. All the documentation I could find describing string substitution used standalone strings, not strings stored in variables. So I do not know and cannot figure out the proper syntax. I have also read similar questions asked here and attempted those solutions to no avail.
Everything in my script works as intended except for this line:
SET %%I=%%%I:%Temp_Dir%=%
It does not change %%I at all. The input to the FOR loop %List% is a text file that looks like this:
C:\Users\UserName\AppData\Local\Temp\Batch_Renaming_Temp\Working\out\bin\codesegment.o
C:\Users\UserName\AppData\Local\Temp\Batch_Renaming_Temp\Working\out\bin\graphic.o
C:\Users\UserName\AppData\Local\Temp\Batch_Renaming_Temp\Working\out\bin\helper.o
C:\Users\UserName\AppData\Local\Temp\Batch_Renaming_Temp\Working\out\bin\main.o
C:\Users\UserName\AppData\Local\Temp\Batch_Renaming_Temp\Working\out\bin\game.out
C:\Users\UserName\AppData\Local\Temp\Batch_Renaming_Temp\Working\out\bin
C:\Users\UserName\AppData\Local\Temp\Batch_Renaming_Temp\Working\out
The final output I get right now is identical to the above list.
The desired output should look like this:
\out\bin\codesegment.o
\out\bin\graphic.o
\out\bin\helper.o
\out\bin\main.o
\out\bin\game.out
\out\bin
\out
I know the syntax is supposed to be:
SET string = C:\Users\UserName\AppData\Local\Temp\Batch_Renaming_Temp\Working\out\bin\codesegment.o
SET string = %string:C:\Users\UserName\AppData\Local\Temp\Batch_Renaming_Temp\Working =%
As I said though, I cannot get it to work using variables in a FOR loop. I am also attempting this method of string substitution because the path of %Temp_Dir% is always at the start of every line and is always found in each line once.
Here is the whole script for reference. I would prefer a one line solution like the one I was attempting. I am aware longer solutions are available but due to reasons beyond my control the one-line string substitution is required.
#ECHO OFF
SETLOCAL EnableDelayedExpansion
SET Proj_Dir="C:\Users\UserName\Desktop\Project"
SET Temp_Dir=%temp%\Batch_Renaming_Temp\Working
SET Counter=1
SET List="%temp%\Batch_Renaming_Temp\LFN_LIST.TMP"
SET List_Final="%temp%\Batch_Renaming_Temp\LFN_LIST.TXT"
ROBOCOPY /E /MIR %Proj_Dir% "%Temp_Dir%" > NUL
CD "%Temp_Dir%"
DIR /A-D /O:N /B /S > %List%
DIR /AD /O:N /B /S | SORT /R >> %List%
TYPE NUL > %List_Final%
FOR /F "usebackq tokens=* delims=" %%I IN (%List%) DO (
REN "%%I" !Counter!
SET /A !Counter+=1
SET %%I=%%%I:%Temp_Dir%=%
ECHO %%I >> %List_Final%
)
Like #Squashman pointed out in the comments, you cannot "set" a FOR variable.
If your variable depends on other variables indirectly, you need to use CALL SET or delayed expansion.
The easiest solution so far:
(for /F "usebackq tokens=8* delims=\" %%x in (%List%) do echo \%%y) > %List_Final%
It uses \ as a delimiter and pass the 8+th arguments to %%y, and redirects all output to %List_Final%
Tested on a Windows 10 laptop, works perfectly.

Get base name of file without file extension

Let's say I'd have a file named "testfile.txt" set on a variable:%File% and I'd like to remove the extension when echoing it . Echo %File:~0,8% would come out as "testfile" but what I want to do is to have it display anything and everything to the left of the ".txt" because I won't always make files which have 8 characters in their name.
Is there a simple solution to this ?
Yep.
for %%I in ("testfile.txt") do echo %%~nI
or
for %%I in ("%file%") do echo %%~nI
Do help for in a cmd console window and see the last two pages for more information on tilde operations.
There is another way to accomplish what you want, using substring substitution similar to your attempts illustrated in your question.
set "file=testfile.txt"
echo %file:.=&rem;%
That substitutes the dot with &rem;. When the variable is evaluated, the batch interpreter treats the newly substituted data as a compound command. And since everything following rem is treated as a remark to be ignored, you're left with only testfile as the output. This will only work if:
you don't include quotation marks in your variable value
your filename only includes the one dot
you don't do it within a parenthetical code block (if statement or for loop) where delayed expansion is required
You can try this:
#echo off
set "file=testfile.txt"
call :removeExtension "%file%"
echo %newFile%
pause
goto :eof
:removeExtension
set "newFile=%~n1"
goto :eof
However, this only works if the file has no path. If it does, you can do this:
#echo off
setlocal EnableDelayedExpansion
set "file=files\testfile.txt"
call :removeExtension "%file%"
echo %newFile%
pause
goto :eof
:removeExtension
set "file=%~1"
set "newFile=!file:%~x1=!"
goto :eof

BATCH - Find string in text file and add a new string after that line

I'm trying to search a text file for a particular string from a bat file. If the string exist, add a new string after it on the next line. I can't seem to get the code below working correctly. Any Ideas?
This is the string i'm searching for in my text file. [/Script/MyGame.Mode]
Here's what the text file looks like.
[/Script/Config.Mode]
Something here 1
Something here 2
[/Script/MyGame.Mode]
Something here 1
Something here 2
[/Script/Edit.Mode]
Something here 1
Something here 2
And here's how I want it to look.
[/Script/Config.Mode]
Something here 1
Something here 2
[/Script/MyGame.Mode]
RedirectReferences=(PackageName="%Package%",PackageURLProtocol="%PackageURLProtocol%",PackageURL="%WebAddress%/%Package%%Ext%",PackageChecksum="")
Something here 1
Something here 2
[/Script/Edit.Mode]
Something here 1
Something here 2
Here's the code I have so far.
#echo off
:GETINFO
echo.
echo.
cls
echo.
echo Let's get some information for your config.
echo Note: The information you enter below is case sensitive. You can copy and paste.
echo.
echo Here's a Package Name example: "DM-MyTest-WindowsNoEditor"
echo.
set /p Package=Enter Package Name:
echo.
echo.
echo.
echo The Package URL Protocol will be "http" or "https"
echo.
set /p PackageURLProtocol=Enter Package URL Protocol:
echo.
echo.
echo.
echo Here's a WebAddress example: "www.myredirect.com/test" (Don't add the trailing /)
set /p WebAddress=Enter Redirect(WebAddress)URL:
echo.
echo.
echo.
echo The file extention is usually ".pak"
echo.
set /p Ext=Enter Map File Extention:
echo.
cls
echo.
echo Please wait... Currently Creating Test References.
:SHOWLINE
echo.
set NewURL=RedirectReferences=(PackageName="%Package%",PackageURLProtocol="%PackageURLProtocol%",PackageURL="%WebAddress%/%Package%%Ext%",PackageChecksum=""^^)
pause
:WRITENEW
set inputfile=game.txt
set outputfile=game.temp.txt
(for /f usebackq^ delims^=^ eol^= %%a in ("%inputfile%") do (
if "%%~a"=="[/Script/MyGame.Mode]" call echo %NewURL%
echo %%a
))>>"%outputfile%"
echo.
pause
When I run the posted code in Command Prompt console I see a syntax error:
) was unexpected at this time.
Apparently the parentheses inside NewURL break things when expanded in the loop.
A straightforward solution would be to delay the expansion by using the call trick:
call echo %%NewURL%%
Alternatively:
setlocal enableDelayedExpansion & echo !NewURL! & endlocal
Or double-escape the closing parenthesis with ^^ (one time for set and another for an expanded value inside the loop):
set NewURL=.............PackageChecksum=""^^)
Another issue is that the output file name is the same as the input file name but it's impossible to redirect output into the same file as you're reading.
Change the output name to a different file. Then replace the original after the loop is finished:
set inputfile=game.txt
set outputfile=game.temp.txt
...................
))>>"%outputfile%"
move/y "%outputfile%" "%inputfile%"
And to change the order of the new string to print it after the found line simply swap the two lines inside the inner loop:
echo %%a
if "%%~a"=="[/Script/MyGame.Mode]" call echo %%NewURL%%

Batch file string manipulation

This is a very specific question, however;
Say I have a batch file running from\located in the directory c:\data\src\branch_1
How do I set my environment variable %buildpath% to c:\build\bin\branch_1 in a batch file?
(To be extra clear, if the same batch file is located in c:\foo\bar\branch_2 I want it to set %buildpath% to c:\build\bin\branch_2)
You should be able to use the environment variable %~dp0 to get you the drive and path of the batch file currently running. From there, it's a not-very-efficient method of stripping off the end of that string character by character and building a new string.
For example, the batch file:
#setlocal enableextensions enabledelayedexpansion
#echo off
set olddir=%~dp0
echo Current directory is: !olddir!
if "!olddir:~-1!" == "\" (
set olddir=!olddir:~0,-1!
)
set lastbit=
:loop
if not "!olddir:~-1!" == "\" (
set lastbit=!olddir:~-1!!lastbit!
set olddir=!olddir:~0,-1!
goto :loop
)
set newdir=c:\build\bin\!lastbit!
echo New directory is: !newdir!
endlocal
running as c:\data\src\branch1\qq.cmd returns the following:
Current directory is: C:\data\src\branch1\
New directory is: c:\build\bin\branch1
As to how it works, you can use !xyz:~n,m! for doing a substring of an environment variable, and negative m or n means from the end rather than the beginning. So the first if block strips off the trailing \ if it's there.
The loop is similar but it transfers characters from the end of the path to a new variable, up until the point where you find the \. So then you have the last bit of the path, and it's a simple matter to append that to your fixed new path.
Old case, but still...
easy way of setting current directory into variable.
#echo off
cd > dir.tmp
set /p directory= <dir.tmp
echo %directory% <-- do whatever you want to the variable. I just did a echo..
del dir.tmp > nul

String processing using Batch Script

I'm currently creating a batch script that has to loop through the lines in a file, checking for some string, and if theres a match prefix that string with a '#' (comment it out).
I'm perfectly new to batch script, all I got this far is:
for /f %%j in (CMakeLists.txt) do (
if "%%j"=="Extensions_AntTweakBar" (
echo lol1
)
if "%%j"=="Extensions_Inspection" (
echo lol2
)
if "%%j"=="Extensions_InspectionBar" (
echo lol3
)
)
So my current issue is, I don't know how to operate on string within batch scripts. If someone could help me out that would be appreciated :)
You can just use the text you want to append followed by your variable generally.
C:\>set MY_VAR=Hello world!
C:\>echo #%MY_VAR%
#Hello world!
C:\>set MY_VAR=#%MY_VAR%
C:\>echo %MY_VAR%
#Hello world!
If you're just doing echo, that's fine. echo #%%j will do what you need.
But if you want to set the line to a variable, you have to enable delayed expansion. Add setlocal ENABLEDELAYEDEXPANSION to the top of your file and then surround your variables with ! instead of %. For example (and notice that I've added delims= to put the entire line in %%j instead of the first word on the line):
#echo off
setlocal ENABLEDELAYEDEXPANSION
set LINE=
for /f "delims=" %%j in (CMakeLists.txt) do (
set LINE=%%j
if "%%j"=="Extensions AntTweakBar" (
set LINE=#%%j
)
if "%%j"=="Extensions Inspection" (
set LINE=#%%j
)
if "%%j"=="Extensions InspectionBar" (
set LINE=#%%j
)
echo !LINE!
)
Given this input file:
Extensions AntTweakBar
some text
Extensions Inspection
Extensions What?
some more text
Extensions InspectionBar
Extensions InspectionBar this line doesn't match because delims= takes all text
even more text
The above script produces this output:
C:\>comment.bat
#Extensions AntTweakBar
some text
#Extensions Inspection
Extensions What?
some more text
#Extensions InspectionBar
Extensions InspectionBar this line doesn't match because delims= takes all text
even more text
And of course removing #echo off will help you debug problems.
But all that being said, you're about at the limit of what you can accomplish with batch string processing. If you still want to use batch commands, you may need to start writing lines to temporary files and using findstr with a regex.
Without a better understanding of what you want inside your loop or what your CMakeLists.txt file looks like, try this on for starters:
FINDSTR "SOMETHING" %%J && ECHO #%%J || ECHO %%J
The && makes the second command (the ECHO) conditional on the first command exiting without an error state, and the || is like a logical OR and it runs when the first one doesn't.
Really, for modifying the internals of a text file you are probably going to be much better off using either sed or awk - win32 binaries can be found in the UnxUtils project.

Resources