Replace a character in a file using a batch script - batch-file

I am new to batch file scripting and need to develop a script to replace a character in a file using a batch script.
I have to replace "servername/ActionService.asmx,1"
with "servername/ActionService.asmx,0"
in file called APP.
Please let me know if there is any solution using only commands.

You can use GNUWin32 sed:
#ECHO OFF &SETLOCAL
set "string=servername/ActionService.asmx,1"
FOR /f %%a IN ('echo "%string%" ^| sed "s/[0-9]/0/"') DO set "newstring=%%~a"
ECHO %newstring%

If you're toggling back and forth between these two states, it might be easier to create two copies of the file with different names, together with a couple of batch files (e.g. actionService1.bat and actionService2.bat) to copy the appropriate file over your APP file.
Otherwise you might consider getting Windows versions of the Unix tools sed and awk, which excel at this type of file manipulation.

The Batch file below assume that there is precisely one line with the target string. This method is relatively fast.
#echo off
for /F "delims=:" %%a in ('findstr /N "servername/ActionService.asmx,1" theFile.txt') do set lineNum=%%a
(for /F "tokens=1* delims=:" %%a in ('findstr /N "^" theFile.txt do (
set "line=%%b"
setlocal EnableDelayedExpansion
if %%a equ %lineNum% (
echo !line:1=0!
) else (
echo(!line!
)
endlocal
)) > theFile.new

#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:: Way the first - suppresses emptylines
FOR /f "delims=" %%i IN (app) DO SET line=%%i&set line=!line:servername/ActionService.asmx,1=servername/ActionService.asmx,0!&ECHO(!line!
ECHO ====================
:: Way the second
FOR /f "delims=" %%i IN ('type app^|findstr /n "$"') DO (
SET line=%%i
set line=!line:servername/ActionService.asmx,1=servername/ActionService.asmx,0!
SET line=!line:*:=!
ECHO(!line!
)
ECHO ====================
GOTO :EOF
Two ways here. You would need to redirect your choice to a new file as you cannot update in-place.

Doing a quick google search I found this http://www.dostips.com/?t=Batch.FindAndReplace

Using a helper batch file called repl.bat from here: http://www.dostips.com/forum/viewtopic.php?f=3&t=3855
type app |repl "servername\/ActionService.asmx,1" "servername/ActionService.asmx,0" >appnew.txt

Related

Find a string into each file of a folder with for loop

I try to find a string "blabla" inside a file. If I find the string I replace it with "bloblo", if not do nothing. And I want to do this operation for all the files that I have in a folder.
When I apply the script on one file, it works well. When I use a for loop it doesn't work. it does not enter inside the for loop
Here is my script:
set "Var1=blabla"
set "Var2=bloblo"
FOR %%i IN (C:\Users\UserName\Desktop\TEST\*.txt) DO (
find /c "%Var1%" %%i
if %errorlevel% equ 1 goto notfound
call PathFile\FUNCTION_REPLACE.cmd %Var1% %Var2% %%i
:notfound
)
I use a script "Function_replace" to replace the values, here is the script:
SetLocal EnableExtensions DisableDelayedExpansion
Set "search=%~1"
Set "replace=%2"
Set "File=%3"
For /F "Tokens=1*Delims=]" %%A In ('Find /V /N ""^<"%File%"^&Break^>"%File%"'
)Do (Set "line=%%B"
SetLocal EnableDelayedExpansion
(If Not "%%B"=="" (Echo(!line:%search%=%replace%!)Else Echo()>>"%File%"
EndLocal)
I used to use directly the call of my replace function for each files of my folder. But it takes a long time to go inside each file. That's why I want to check before going inside each file, if the string exists or not (by using find /c).
Can you spot where is the issue coming from?
Based upon your latest edit, here's an example which sends only the files containing the string to be replaced, to the sub-function:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "search=%~1"
Set "replace=%~2"
For /F Delims^=^ EOL^= %%A In ('FindStr /LIMP "%search%" *.*')Do Call :Sub "%%A"
GoTo :EOF
:Sub
Set "File=%~1"
For /F "Tokens=1*Delims=]" %%A In ('Find /V /N ""^<"%File%"^&Break^>"%File%"'
)Do (Set "line=%%B"
SetLocal EnableDelayedExpansion
(If Not "%%B"=="" (Echo(!line:%search%=%replace%!)Else Echo()>>"%File%"
EndLocal)
Please note that the FindStr command uses only example options, whilst the /M option is important to this solution you should check the output from FindStr /? to determine which of the others you would consider the most appropriate.
Why not simply list all files that has the string and exclude the files that don't? That seems like a more obvious plan to me:
#echo off
set "search=blabla"
for /f "delims=" %%i in ('findstr /m %search% "%USERPROFILE%\Desktop\TEST\*.txt"') do (
echo found "%search%" in "%%~fi"
)
If you want to still show files that does not contain the path, then #stephan already posted a comment on how to, no need for me to repeat.

Batch - Returning full path from a dir /b

I am traversing folders on a drive, collecting file names with specific extensions, and building a string which is later used in a command line switch. When I find a qualifying file I need to know its full path as this is what is required by the command line. I currently use "%~dp0%%a\%%b" to build the full path, but I can see that may have limitations later on when the batch becomes more complex (e.g. it digs deeper into sub folders). I am hoping there is a way to replace "%~dp0%%a\%%b" with the path to the located file. Thank you:
#ECHO OFF
for /f "usebackq tokens=*" %%a in (`dir /b /a:d`) do (
pushd %%a
setlocal ENABLEDELAYEDEXPANSION
for /f "delims=" %%b in ('dir /b "*.E01" "*.L01" "*.AD1" 2^>nul') do (
SET EVIDENCE_STR=!EVIDENCE_STR! /e:"%~dp0%%a\%%b"
)
IF DEFINED EVIDENCE_STR (
ECHO !EVIDENCE_STR!
) ELSE (
ECHO No evidence files located in: %%a
)
endlocal
SET EVIDENCE_STR=
popd
)
PAUSE
Why do you need to create 2 loops, each running a dir command to find files? Why not just do for /R loop? Here is an example:
#echo off
set "files=*.E01 *.L01 *.AD"
for /R %%a in (%files%) do echo %%a
Simply use "Sub"-Option: /S of the DIR-Command:
Dir /B /S C:\*.jpg
cause it is that equivalent to:
#echo off
set "DirPath=C:\"
set "files=*.jpg"
for /R %DirPath% %%a in (%files%) do echo %%a
and so you should got the same result in each script.
The Problem: If you don't want any deep of SubDirectorys, you've to filter out these and so you may lose time - in both solutions.

Editing text in a file using a batch file

I am trying to edit some lines of text within a text file using a batch file. The lines are as below -
#TEST_RSA_KEY=1
#V3SERVER0=109.73.122.107;29006
#DOWNLOAD0=109.73.122.112;29006
I need to change these to be
#TEST_RSA_KEY=0
#V3SERVER0=91.207.36.31;29006
#DOWNLOAD0=91.207.36.37;29006
How would you recommend I do this via a batch file, I am very new to this and have very basic knowledge so simple and clear answers please! :) Thank you
Not tested
#echo off
set file_loc=C:\text.file.txt
for "usebackq tokens=* delims=" %%a in ("%file_loc%") do (
set "%%a"
)
set "#TEST_RSA_KEY=0"
set "#V3SERVER0=91.207.36.31;29006"
set "#DOWNLOAD0=91.207.36.37;29006"
set #>"%file_loc%"
I've assumed that all properties start with #
Note - I have not tested any of the code examples below, so there could be bugs. But I have successfully used all of the techniques below in the past, and any fixes (if necessary) should be fairly trivial.
All of my solutions below assume that spaces never appear in any of the name value pairs. Each of the solutions could be adapted to support spaces, if necessary.
If the order of the lines is not important, then the following pure batch solution works well and is quite fast. I use FINDSTR to remove the lines that are to be altered, before appending the new values to the end:
#echo off
>"file.txt.new" (
findstr /v /b "#TEST_RSA_KEY= #V3SERVER0= #DOWNLOAD0=" "file.txt"
echo #TEST_RSA_KEY=0
echo #V3SERVER0=91.207.36.31;29006
echo #DOWNLOAD0=91.207.36.37;29006
)
move /y "file.txt.new" "file.txt" >nul
If the order of the lines is important, then I would use my JREPL.BAT utility - a hybrid JScript/batch regular expression text processor. It is pure script that runs natively on any Windows machine from XP onward. I recommend putting the script within a directory that is listed within your path. I like to use "c:\utils" for all my non-standard utilities.
A simple one replacement at a time strategy is the simplest effective solution, and it should be plenty fast unless the file is exceptionally large:
#echo off
call jrepl "^(#TEST_RSA_KEY)=.*" "$1=0" /f "file.txt" /o -
call jrepl "^(#V3SERVER0)=.*" "$1=91.207.36.31;29006" /f "file.txt" /o -
call jrepl "^(#DOWNLOAD0)=.*" "$1=91.207.36.37;29006" /f "file.txt" /o -
The above strategy can be made easy to maintain (add additional replacements) with a bit more code, as long as none of the strings contain * or ?, and no value begins with =:
#echo off
for %%A in (
"#TEST_RSA_KEY=0"
"#V3SERVER0=91.207.36.31;29006"
"#DOWNLOAD0=91.207.36.37;29006"
) do for /f "tokens=1* delims==" %%B in (%%A) do (
call jrepl "^(%%B)=.*" "$1=%%C" /f "file.txt" /o -
)
The * and ? limitation can be removed if the replacement strings are already in a separate file (replace.txt):
#echo off
for /f "tokens=1* delims==" %%A in (replace.txt) do (
call jrepl "^(%%A)=.*" "$1=%%B" /f "file.txt" /o -
)
Or the replacement strings could be embedded within the batch script itself
#echo off
for /f "tokens=1* delims==" %%A in ('findstr "^#" "%~f0"') do (
call jrepl "^(%%A)=.*" "$1=%%B" /f "file.txt" /o -
)
exit /b
#TEST_RSA_KEY=0
#V3SERVER0=91.207.36.31;29006
#DOWNLOAD0=91.207.36.37;29006
The entire job can be done much more efficiently in one pass if you are willing to do the capture group bookkeeping and prepare a long command line (8191 byte length max):
#call jrepl "(#TEST_RSA_KEY)=.* (#V3SERVER0)=.* (#DOWNLOAD0)=.*" "$2=0 $4=91.207.36.31;29006 $6=91.207.36.37;29006" /b /t " " /f "file.txt" /o -
A variation of any of the prior 3 methods could be used to make this efficient solution easier to maintain, as long as ! never appears in the values. For example:
#echo off
setlocal enableDelayedExpansion
set "find="
set "repl="
set "n=0"
for /f "tokens=1* delims==" %%A in ('findstr "^#" "%~f0"') do (
set "find=!find! (%%A)=.*"
set /a n+=2
set "repl=!repl! $!n!=%%B"
)
call jrepl "!find:~1!" "!repl:~1!" /b /t " " /f "file.txt" /o -
exit /b
#TEST_RSA_KEY=0
#V3SERVER0=91.207.36.31;29006
#DOWNLOAD0=91.207.36.37;29006

Batch - Search for part/exact name and copy line from text file into batch as var

This information below is contained in a text file and formatted as such.
/var/www/xxx/html/videos/video_folder_1
/var/www/xxx/html/videos/video_folder_2
/var/www/xxx/html/videos/video_folder_3
/var/www/xxx/html/videos/video_folder_4
/var/www/xxx/html/videos/video_folder_5
/var/www/xxx/html/videos/video_folder_6
/var/www/xxx/html/videos/video_folder_7
I also have a variable called %file_name% in the batch file already defined.
So lets say that is it is %file_name% = V001-video_folder_6.mp4
As you can see there is some more extra information, V001- and .mp4.
I would like to use the var %file_name% to search the text file and return the entire line. In this case it would return /var/www/xxx/html/videos/video_folder_6 and then put this information in a new var, let us say, %folder_path%.
I think I would use findstr however I have been playing around and not getting the best results.
The problem with the methods that use findstr is that they are slow, because they require to execute findstr.exe (a ~30KB file) each time. A simpler/faster solution is to use just internal Batch commands with the aid of an array. If the number of names to process is large, the difference in time between the two methods may be marked.
#echo off
setlocal EnableDelayedExpansion
rem Load the lines from text file into an array with the last part as index:
for /F "delims=" %%a in (test.txt) do (
set "line=%%a"
for %%b in (!line:/^= !) do set "lastPart=%%b"
set "folder[!lastPart!]=%%a"
)
set "file_name=V001-video_folder_6.mp4"
rem Get the folder from file_name:
for /F "tokens=2 delims=-." %%a in ("%file_name%") do set "folder_path=!folder[%%a]!"
echo Folder path is: %folder_path%
Let us assume the posted lines are in file Test.txt in current working directory.
#echo off
set "file_name=V001-video_folder_6.mp4"
for /F "tokens=2 delims=-." %%A in ("%file_name%") do set "folder=%%A"
for /F "delims=" %%P in ('%SystemRoot%\System32\findstr.exe "/C:%folder%" Test.txt') do (
set "folder_path=%%P"
goto NextCommand
)
:NextCommand
echo Full folder path is: %folder_path%
Open a command prompt window, enter the command for /?, hit key RETURN or ENTER and read output help to understand this little code.
The command goto inside FOR loop results in an immediate exit from loop processing output of findstr.exe after first found line containing the folder path of interest.
Perhaps better in case of searched folder is not found in text file:
#echo off
set "file_name=V01-VIDEOS for school (Miss Patrick).mp4"
for /F "tokens=2 delims=-." %%A in ("%file_name%") do set "folder=%%A"
for /F "delims=" %%P in ('%SystemRoot%\System32\findstr.exe "/C:%folder%" Test.txt') do (
set "folder_path=%%P"
goto FoundFolder
)
echo "%folder%" not found in file Test.txt.
pause
goto :EOF
:FoundFolder
echo Full folder path is: "%folder_path%"
pause
This should work:
::file_name=V001-video_folder_6.mp4
::file containing folder paths is called paths.txt
for /f "tokens=2 delims=-." %%a in ("%file_name%") do set FN=%%a
for /f %%a in ('findstr /E /L "%FN%" "paths.txt"') do set folder_path=%%a
echo %folder_path%
Which does what you want in effectively two lines.

Find and Replace matching string in file using batch script

I have written a simple script which will find and replace a matching string. I am getting issue in the output file. Following is my script
#echo off
setlocal ENABLEDELAYEDEXPANSION
for /f "tokens=1 delims=" %%a in ('FINDSTR "^applicationPort" "E:\BATCH-SCRIPTING\Version.txt"') do (
echo Installed version is %%a
set oldPort=%%a
)
for /f "tokens=1 delims=" %%b in ('FINDSTR "^applicationPort" "E:\BATCH-SCRIPTING\Sample.txt"') do (
echo Installed version is %%b
set newPort=%%b
)
set SEARCHTEXT="applicationPort=8080"
set REPLACETEXT="applicationPort=8090"
set file="E:\BATCH-SCRIPTING\Sample.txt"
for /f "tokens=1,* delims=]" %%A in ('"type %file% |find /n /v """') do (
set "line=%%B"
if defined line (
call echo %%line:%SEARCHTEXT%=%REPLACETEXT%%%>> %file%_new
) ELSE echo.
)
move /Y %file%_new %file% > nul
In my output file the expected output should be : applicationPort=8090, but i am getting 8080=applicationPort=8090=8080.
Can anyone help me in resolving this issue.
Look at what your key replacement line would like like after the first round of variable expansion:
call echo %%line:%SEARCHTEXT%=%REPLACETEXT%%%>> %file%_new
becomes
call echo %line:applicationPort=8080=applicationPort=8090%>>"E:\BATCH-SCRIPTING\Sample.txt"
The search/replace parser ends the search phrase at the first = it sees. So after the CALL it searches for applicationPort and replaces it with 8080=applicationPort=8090. Perfectly logical.
The bad news is there is absolutely no way to escape the = in the search term. Replacing = is extremely difficult using a batch file. There are solutions, but I don't recommend them. Instead, I would use my hybrid JScript/batch utility called REPL.BAT. It is pure script that will run on any Windows machine from XP onward. It performs a regex search and replace on stdin and writes the result to stdout. Full documentation is embedded within the script.
#echo off
type "E:\BATCH-SCRIPTING\Sample.txt"|repl "applicationPort=8080" "applicationPort=8090" >"E:\BATCH-SCRIPTING\Sample.txt_new"
move /y "E:\BATCH-SCRIPTING\Sample.txt_new" "E:\BATCH-SCRIPTING\Sample.txt"
REPL.BAT is much simpler and faster (and more powerful) than anything you can do using pure batch script.

Resources