Find and replace not working in batch script - batch-file

I'm trying to make a batch script with find and replace option but the batch script doesn't do anything instead just show the blinking cursor and gets stuck there.
Here's the coding I'm using:
setlocal
set this=abhinav2
for /f "delims=" %%i in ('^<test\abc.new findstr /n "^"') do ('
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:*:=!"
if not "!line!"=="!line:<xyz>mnishamk<abc>" set "line=<xyz>%this%<abc>"
(echo(!line!)>>test\new.abc
endlocal
)
)
I can't simply replace mnishamk with abhinav2 as there are lots of names with mnishamk present in the file.

You have a syntax issue, see set /? for help and try this:
#echo off&setlocal enabledelayedexpansion
set "line=<xyz>mnishamk<abc>"
set "this=abhinav2"
if not "!line!"=="!line:<xyz>mnishamk<abc>=!" set "line=<xyz>%this%<abc>"
echo !line!
output is:
<xyz>abhinav2<abc>
And this also works:
set "line=!line:<xyz>mnishamk<abc>=<xyz>%this%<abc>!"

#ECHO off
setlocal
DEL \test\new.abc /F /Q
set this=abhinav2
for /f "delims=" %%i in ('^<\test\abc.new findstr /n "^"') do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:*:=!"
if not "!line!"=="!line:<xyz>mnishamk<abc>=!" set "line=!line:<xyz>mnishamk<abc>=<xyz>%this%<abc>!"
echo(!line!>>\test\new.abc
endlocal
)
FC \test\abc.new \test\new.abc
This worked for me...

Related

Reading File Name using batch

I'm working on a new project, and I would like some help.
I have a script that I put together and it works great, but would like to see if we can update it
What I need help with is making the batch files read 2 parts of it's own file name and use that to match and replace content of many different .txt files
these are my bat script names, I have made over 100 individual batch scripts
(50) Kentucky.bat
(60) New_York.bat
(90) Texas.bat
I have a total of 7 different .txt files and each txt files looks like this
cmmd.txt
| Kentucky
| New_York
| Texas
| Houston
This is how I setup my script, I'm ok with the setup, it does what it needs to
#echo off
setlocal enableextensions disabledelayedexpansion
set "search=Kentucky"
set "replace=50"
set "SOURCE=%~dp0New Folder 1"
set "textFile1=cmmd.txt"
set "textFile2=cwab.txt"
set "textFile3=ecbc.txt"
set "textFile4=elic.txt"
set "textFile5=tcpd.txt"
set "textFile6=uadu.txt"
set "textFile7=urdm.txt"
for /f "delims=" %%i in ('type "%source%\%textFile1%" ^& break ^> "%source%\%textFile1%" ') do (
set "line=%%i"
setlocal enabledelayedexpansion
>>"%source%\%textFile1%" echo(!line:%search%=%replace%!
endlocal
)
for /f "delims=" %%i in ('type "%source%\%textFile2%" ^& break ^> "%source%\%textFile2%" ') do (
set "line=%%i"
setlocal enabledelayedexpansion
>>"%source%\%textFile2%" echo(!line:%search%=%replace%!
endlocal
)
for /f "delims=" %%i in ('type "%source%\%textFile3%" ^& break ^> "%source%\%textFile3%" ') do (
set "line=%%i"
setlocal enabledelayedexpansion
>>"%source%\%textFile3%" echo(!line:%search%=%replace%!
endlocal
)
for /f "delims=" %%i in ('type "%source%\%textFile4%" ^& break ^> "%source%\%textFile4%" ') do (
set "line=%%i"
setlocal enabledelayedexpansion
>>"%source%\%textFile4%" echo(!line:%search%=%replace%!
endlocal
)
for /f "delims=" %%i in ('type "%source%\%textFile5%" ^& break ^> "%source%\%textFile5%" ') do (
set "line=%%i"
setlocal enabledelayedexpansion
>>"%source%\%textFile5%" echo(!line:%search%=%replace%!
endlocal
)
for /f "delims=" %%i in ('type "%source%\%textFile6%" ^& break ^> "%source%\%textFile6%" ') do (
set "line=%%i"
setlocal enabledelayedexpansion
>>"%source%\%textFile6%" echo(!line:%search%=%replace%!
endlocal
)
for /f "delims=" %%i in ('type "%source%\%textFile7%" ^& break ^> "%source%\%textFile7%" ') do (
set "line=%%i"
setlocal enabledelayedexpansion
>>"%source%\%textFile7%" echo(!line:%search%=%replace%!
endlocal
)
call "%~dp0\(60) New_York.bat"
So this will be the end results after I run the first .bat and it calls the rest
cmmd.txt
| 50
| 60
| 90
| Houston
So I would like is to set this up where set "search=Kentucky" and set "replace=50" are setup by using the file name of the .bat file instead of me editing each Search and Replace
If you noticed that I added a call at the end and it works great, but is there a way for a script to call the next .bat file without me having to edit each .bat file
as you can see, I named my files by numeric order, and each .bat will call the next .bat file
(50) Kentucky.bat - this will call (60) New_York.bat
(60) New_York.bat - this will call (90) Texas.bat
(90) Texas.bat - the last one will not have a call
Having something like that will help save so much time, since all I would have to do is rename the .bat files as I need them, and that's it
I do appreciate any help and for all your time
meanwhile I will continue to make my .bat files
Repeating code is bad (error-prone and hard to maintain). Consolidate and use parameters where needed (where the code differs). This leaves you with just one script and a textfile to maintain the replacement parameters, looking like:
50,Kentucky
60,New_York
90,Texas
The code:
#echo off
setlocal
REM get vars from csv
for /f "usebackq tokens=1,2 delims=," %%a in ("replacements.csv") do call :replace "%%~a" "%%~b"
:: REM get vars from parameters
:: call :replace "%~1" "~2"
goto :eof
:replace
REM replace in all matching files:
set "source=%~dp0New Folder"
for %%a in ("%source%\*.txt") do (
for /f "delims=" %%i in ('type "%%a" ^& break ^> "%%a" ') do (
set "line=%%i"
setlocal enabledelayedexpansion
>>"%%a" echo(!line:%~2=%~1!
endlocal
)
)
In case you need it, I included a way to use parameters (commented out with ::. Use either the for loop (reading the textfile) or the parameters like
replace.bat 20 "New Jersey"
(both methods support spaces)
See for /? for the ~<modifer><var> modifiers and call /? for the %~<number> parameters.

Loop through files in folder, replace content and Save as new Name

I need to loop through filed end with .edi in my folder, replace a character in the content and then save the file in another folder with "_updated"on the end.
e.g.
C:/Test/FileName.edi replace ' in file with ^ and save the file into C:/Test/Output/FileName_Updated.edi
I've tried the following code and it works up until the saving the filename part, I've got confused somewhere, I don't usually write batch scripts:
#echo off
setlocal enabledelayedexpansion
for %%f in (C:\Test\*.edi) do (
set "input=C:\Test\"
SET "output=C:\Test\Output\"
for %%a in (%%f) do (
set "output=%output%%%~na_update.%%~xa"
)
(for /f "delims=" %%i in (%%f) do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:'=^!"
echo(!line!
endlocal
)))>> %output%
)
Figured it out with help from aschipfl
#echo off
setlocal enabledelayedexpansion
for %%f in (C:\Users\CHRW\Desktop\EDILocalTest\*.edi) do (
SET "output=C:\Users\CHRW\Desktop\EDILocalTest\Output\"
for %%a in (%%f) do (
set "outputfile=!output!%%~na_update%%~xa"
)
(for /f "delims=" %%i in (%%f) do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:'=^!"
echo(!line!
endlocal
))>> !outputfile!
)
#echo off
setlocal enabledelayedexpansion
for %%f in (C:\Test\*.edi) do (
set "input=C:\Test\"
SET "output=C:\Test\Output\"
(for /f "delims=" %%i in (%%f) do (
set "line=%%i"
rem setlocal enabledelayedexpansion
set "line=!line:'=^!"
echo(!line!
rem endlocal
)))>> "%output%%%~nf_update.%%~xf"
)
Since you were changing the value of output within the loop, the redirection should have been to !output! not %output% - the changed value of output, not the value of output at the time the outer for loop was parsed.
Since %%f contains a filename, there's no need to re-parse it. Easier to construct the output filename in-line
Since delayedexpansion has been invoked at the start of the procedure, there's no need to re-invoke it and close the new invocation. I've REMmed-out those lines as it may be that you are presenting abbreviated code.

Batch, use wildcard in set

I want to put a batch file to modify a line in a file in a GPO.
The problem I have is the path is different for each user.
So, I tried to use a wildcard in my path but it doesnt work.
This bat is working:
#echo off &setlocal
setlocal enabledelayedexpansion
set "search=test"
set "replace=test2"
set "textfile=%appdata%\Thunderbird\Profiles\5xu9scdm.default\prefs.js"
set "newfile=%appdata%\Thunderbird\Profiles\5xu9scdm.default\prefs2.js"
(for /f "delims=" %%i in (%textfile%) do (
set "line=%%i"
set "line=!line:%search%=%replace%!"
echo(!line!
))>"%newfile%"
del %textfile%
rename %newfile% prefs.js
endlocal
But if I use a wildcard in the set, it doesnt work anymore.
#echo off &setlocal
setlocal enabledelayedexpansion
set "search=test"
set "replace=test2"
set "textfile=%appdata%\Thunderbird\Profiles\*.default\prefs.js"
set "newfile=%appdata%\Thunderbird\Profiles\*.default\prefs2.js"
(for /f "delims=" %%i in (%textfile%) do (
set "line=%%i"
set "line=!line:%search%=%replace%!"
echo(!line!
))>"%newfile%"
del %textfile%
rename %newfile% prefs.js
endlocal
How can I fix this ?
You approach does not work, because wild-cards can only occur in the last element of a path. In addition, for /F is not capable of handling wild-cards. So you need to wrap around a for /D loop to resolve the wild-cards, like this (supposing there is only a single matching directory *.default):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "search=test"
set "replace=test2"
set "rootdir=%appdata%\Thunderbird\Profiles\*.default"
set "textfile=prefs.js"
set "newfile=prefs2.js"
for /D %%j in ("%rootdir%") do (
> "%%~j\%newfile%" (
for /F "usebackq delims=" %%i in ("%%~j\%textfile%") do (
set "line=%%i"
setlocal EnableDelayedExpansion
set "line=!line:%search%=%replace%!"
echo(!line!
endlocal
)
)
> nul move /Y "%%~j\%newfile%" "%%~j\%textfile%"
)
endlocal
exit /B
What I changed besides inserting the for /D loop:
delayed expansion is toggled within the loop, so exclamation marks in the text files are not lost;
all paths are properly quoted; to use a quoted file path in for /F, usebackq is required;
the replacement of the original file by the modified one is done by a single move command rather than del plus rename;

Batch get filename from path

Hi I don't have much experience in batch-programming and have a problem. I have a .bat script that reads a file with a list of paths and i want to get the filename of these paths. I use the script in cygwin.
My code in the Script:
for /F %%a in (error1.txt) do (
set value=%%a
FOR /F %%I IN ("%value%") DO SET MYPATHFILE=%%~nxI
)
When i run the Script %value% is empty.
Value of error1.txt:
a/b/c/d/TextIWant
you need delayed expansion or you can directly use %%a:
for /F %%a in (error1.txt) do (
FOR /F %%I IN ("%%a") DO SET MYPATHFILE=%%~nxI
)
or
setlocal enableDelayedExpansion
for /F %%a in (error1.txt) do (
set value=%%a
FOR /F %%I IN ("!value!") DO SET MYPATHFILE=%%~nxI
)
It looks like you will need Delayed Expansion.
The current problem is, that you want to use a variable in the same set of brackets where you changed the value in (the surrounding For-Loop).
Add setlocal EnableDelayedExpansion to your code at the top and change the %value% to !value!
You can test the problem yourself with this code:
#echo off
setlocal EnableDelayedExpansion
set foo=bar
For /L %%a (1,2,1) do (
set foo=foobar
echo.old value %foo%
echo.new value !foo!
)
I hope it helped :)
Greetings
geisterfurz007

MS-DOS batch script: assignment operation

I am referring to below threat Batch files: How to read a file?. For retrieving the line by line from a text file. I am using the below script:
#echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ paths.txt"`) do (
set "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!"
echo !var!
ENDLOCAL
)
Code is working fine! The values in !var! can not assign to any variable. :( I struct there, Please anyone help to read line by line and I wish to assign to some variable and want to manipulate that variable. Please help to solve this situation.
Update:
#ECHO off
CLS
SET PROJ_DIR=D:\workspace\proj
SET PROMO_DIR=D:\TEST
SET SOURCE_CODE=\Source Code
SETLOCAL DisableDelayedExpansion
for /f %%a in (paths.txt) do (
SET "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!"
set FILE_PATH=!var://www.domain.com/path/dir=!
SET FILE_PATH=!FILE_PATH:/=\!
SET PROMO_FILE_PATH=!PROMO_DIR!!SOURCE_CODE!!FILE_PATH!
FOR %%i IN ("!PROMO_FILE_PATH!") DO SET FOLDER_PATH=%%~dpi
FOR %%i IN ("!PROMO_FILE_PATH!") DO SET FILE_NAME=%%~nxi
IF EXIST "!FOLDER_PATH!" GOTO F3
MKDIR "!FOLDER_PATH!"
:F3
IF NOT EXIST "!PROJ_DIR!!FILE_PATH!" GOTO F4
COPY "!PROJ_DIR!!FILE_PATH!" "!FOLDER_PATH!"
:F4
ECHO Cannot find the file under "!PROJ_DIR!!FILE_PATH!"
ENDLOCAL
)
SET CLOSE_CONFIRM=
SET /P CLOSE_CONFIRM=Press any key to close the window...%=%
paths.txt
//www.domain.com/path/dir/dir1/dir2/file1.txt
//www.domain.com/path/dir/dir1/dir2/file2.txt
//www.domain.com/path/dir/dir1/dir2/file3.txt
//www.domain.com/path/dir/dir1/dir2/file4.txt
//www.domain.com/path/dir/dir1/dir3/file1.txt
Command Output
1 file(s) copied.
Cannot find the file under "D:\workspace\proj\dir1\dir2\file1.txt"
1 file(s) copied.
Cannot find the file under "D:\workspace\proj\dir1\dir2\file2.txt"
Press any key to close the window...
thanks..
The key is the delayed expansion, expand your variables inside of parenthesis always with ! not with %.
A sample that changes X with Y
#echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ paths.txt"`) do (
set "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!"
set "myVar=!var!"
set "myVar=!myVar:X=Y!"
echo X replaced with Y =!myVar!
ENDLOCAL
)
In your updated version the goto :label stops the for-loop immediatly
Better rewrite it to IF-Blocks
IF NOT EXIST "!FOLDER_PATH!" (
MKDIR "!FOLDER_PATH!"
)
IF EXIST "!PROJ_DIR!!FILE_PATH!" (
COPY "!PROJ_DIR!!FILE_PATH!" "!FOLDER_PATH!"
) ELSE
(
ECHO Cannot find the file under "!PROJ_DIR!!FILE_PATH!"
)
The other answers here cover the tricky bits of delayed expansion in this code. I want to add that you can often avoid most delayed expansion problems by rolling the parentheses out into a subroutine.
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ paths.txt"`) do call :HandlePath %%a
goto :eof
================
:HandlePath
set "var=%*"
set "var=%var:*:=%"
echo %var%
goto :eof
I find this code easier to maintain because each line is parsed an executed exactly when you would expect.
If you want to read each line and manipulate it:
SETLOCAL EnableDelayedExpansion
FOR /F "tokens=*" %%a IN (paths.txt) DO (
set var=%%a
ECHO %var%
PAUSE
)
ENDLOCAL
If you are trying to search a string from a file and manipulate it:
SETLOCAL EnableDelayedExpansion
FOR /F "tokens=* usebackq" %%a IN (`FIND /I 'string to search for' "C:\folder\paths.txt"`) DO (
set var=%%a
ECHO %var%
PAUSE
)
ENDLOCAL
If you are trying to search a string and manipulate each word in the string:
SETLOCAL EnableDelayedExpansion
FOR /F "usebackq tokens=1-999 delims= " %%a IN (`FIND /I 'string to search for' "C:\folder\paths.txt"`) DO (
REM %%a = first word %%b = second word etc. through the alphabet
set var1=%%a%%b%%c
set var2=%%d
ser var3=%%e
ECHO %var1% %var2% %var3%
PAUSE
)
ENDLOCAL
This works for me:
#echo off
SETLOCAL EnableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ paths.txt"`) do (
set var=%%a
set var=!var:*:=!
echo !var!
)
ENDLOCAL

Resources