Batch Command to replace text in file - batch-file

I know this question is asked many times, but I didn't get the answer for what I am searching.
I want to replace a pattern using windows .bat file.
I know how to replace X with Y.
But I am trying to replace say installPath with C:\Programfiles\Install\.
Here, I am facing issues as the new value string contains \ i.e special character.
Please let me know how I can replace this.

This works fine for me
set p=installPath
set p=%p:installPath=C:\Programfiles\Install\%
echo %p%

Followinf script will find the string in the file and replace with another string.
EX. "installPath" will be replaced with "C:\Programfiles\Install"
#echo off
for /f "usebackq tokens=*" %%a in ("test.txt") do call :Replace "%%a"
del "test.txt"
rename "newfile.txt" test.txt
exit /b
:Replace
set str1=%~1
set str1=%str1:installPath=C:\Programfiles\Install%
echo.%str1%>>"newfile.txt"
exit /b

Perhaps this tool might help you:
http://sourceforge.net/projects/fart-it/

This should work... By the way, this is my first post on this website.
The following uses delayed expansion so that you have two different 'variable symbols' to play with:
setlocal enabledelayedexpansion
set iPath=installPath
set input=C:\Programfiles\Install\
set p=!iPath:installPath=%input%!
Hope this helps

Related

Batch-File: Find String inside String does not work

I have tried to use the answer mentioned from here: [Find Substring in String] (Batch file: Find if substring is in string (not in a file))
I try to adapt the solution mentiones in the commands, so that I have my SearchVal saved inside a variable so this can be changed during runtime.
Minimal example:
set searchVal="cde"
set str1="abcdef"
setlocal enabledelayedexpansion
if not "x!str1:%searchVal%=!"=="x%str1%" echo It contains my subs
endlocal
pause
In my opinion this little batch should display that the strings contains my subs, however nothing is shown and I do not know why as I directly make use of the solution that should be working.
EDIT
Thanks to the commands I found my mistake.
In my current situation I look at files inside a folder and save the filename inside an array while doing a for-loop:
for /f "tokens=1 delims=" %%G in ('pathToFolder\*.properties /b') do (
if not "%%~G:%searchVal%=!"=="%%~G" echo It contains my subs !ID_Properties!
set filename[!ID_Properties!]=%%~G
set /a ID_Properties+=1
)
... where ID_properties is just a counter and searchVal my string I am looking for. Does anyone know how I can use the %%G inside the loop in the correct way so the search works as before?
Your for-loop syntax is not correct it seems like a mixture between executing a dir command and looping through files. I'll stick with the dir command option and using usebackq.
#echo off
setlocal EnableDelayedExpansion
set searchVal=cde
set ID_Properties=0
for /f "usebackq tokens=1 delims=" %%G in (`dir pathToFolder\*.properties /b`) do (
set file=%%G
if not "!file:%searchVal%=!"=="!file!" (
echo It contains my subs !ID_Properties!
set filename[!ID_Properties!]=!file!
set /a ID_Properties+=1
)
)
Filling the array is only done if the file contains your searchVal; don't know if this was/is you intention.
a For loop might be a bit much, depending on what you plan to do with the output. findstr is maybe a shorter option:
findstr /im "cde" *.properties && echo - found || echo not found
and add /s if you require recursive search through subdirectories:
findstr /ims "cde" *.properties && echo - found || echo not found

Using Windows ren command to remove ! from filename

I have a bunch of files that are in the following format
filename-!#.ext
where # is an incrementing number to prevent collisions. I would like to just remove the ! from the filename so it reads as
filename-#.ext
It seems like I could do this with the ren command and wildcards but having a hard time getting it to work. I tried running this:
ren *!?.ext *?.ext
My thought is the * should match the filename- part, then !, then the ? for the numeric. However, the resulting file is named this:
filename-!#.ext.ext
and I can't quite figure out why.
The filename part can be dynamic, but won't contain any !'s. Any ideas?
I think you'll have to resort to a small batch file for this:
#echo off
setlocal
for %%a in (*!*.ext) do call :remove "%%~a"
goto :eof
:remove
set "FROM=%~1"
set "TO=%FROM:!=%"
ren "%FROM%" "%TO%"
goto :eof
The above will – for all files containing an exclamation mark and extension ext – call the remove function. This takes the original name (FROM) and determines the new name (TO) by using the %var:find=replace% syntax to remove any exclamation mark (replaces it with an empty string).
Notes
You cannot use find/replace with either %%a or %0 type variables, so you have to assign it to a named variable first.
I originally tried doing this "inline" with the for statement (e.g. for ... ( ending )) but to do that, you would have to enable delayed-expansion (because you would need to access a named variable in a loop). However, delayed-expansion uses ! (instead of %) to reference variables and this got in the way of the ! we were trying to remove. There may be a way of doing this, but I haven't found it. Using call will be slightly slower, but not significantly unless you've got thousands of files.
You don't really need to create TO (you could perform the replacement on the ren command-line) but I used it for clarity.
This will work for all files with an exclamation mark: it doesn't check the bit after is numeric.
I think it is not a good idea to let rename select the files, but instead do it with a for-loop and then execute the rename for every file:
for %%F in (*!*) do (
set "nxF=%%~nxF"
call ren "%%nxF%%" "%%nxF:!=%%"
)
You really have to use call here instead of delayedExpansion, because delayedExpansion would destroy the rename-arguments (because they contain !)
Based upon your provided information and just for the sake of offering something a little different, you could let delayed expansion do the work for you, (as it will remove the unwanted exclamation mark for you).!
#For %%A In ("*-!?.ext") Do #Set "_=%%A" & SetLocal EnableDelayedExpansion & Ren "!_!" "%%A" & EndLocal
You could probably also do it with a nested for loop:
#For %%A In ("*-!?.ext") Do #For /F "Tokens=1*Delims=!" %%B In ("%%A") Do #Ren "%%A" "%%B%%C"
…and from the Command Prompt:
For %A In ("*-!?.ext") Do #For /F "Tokens=1*Delims=!" %B In ("%A") Do #Ren "%A" "%B%C"

batch doen't read text file till save it first

My code stops at line 3 in the .dat file ,but when i save the .dat file it reads all the lines and work properly why this happening and what to do??
this is code my data contain Latina characters and symbols.
#ECHO Off
SET "sourcedir=D:\yyyyy\Orgin_file_Ma\MA_SMS"
SET "destdir=D:\llllll\STG_file_Ma"
FOR %%f IN ("%sourcedir%\*.dat") DO > "%destdir%\%%~nf.txt" (
FOR /f "usebackqdelims=" %%a IN ("%%f") DO (
set Typ=SMS
ECHO %%a^|!Typ!
)
)
This is effectively the same question you asked yesterday.
An answer cannot be provided unless you change your code to something that works; try this:
#ECHO OFF
SET "SOURCEDIR=D:\yyyyy\Orgin_file_Ma\MA_SMS"
SET "DESTDIR=D:\llllll\STG_file_Ma"
SET "TYP=SMS"
FOR %%F IN ("%SOURCEDIR%\*.dat") DO FOR /F "USEBACKQ DELIMS=" %%A IN ("%%F"
) DO >"%DESTDIR%\%%~nF.txt" ECHO %%A^|%TYP%
After confirming the structure of the above script is correct, add it to your question above by way of the edit facility and provide much more information on those dat files.
Depending upon those dat files it is likely that ECHO may not be the correct command to use.
Thank you for your helpful answers i learned a lot,i solved my problem by using Powershell instead of batch.

Batch: Set one directory up path in variable

Hi i am mapping a shell script code to batch script so i came across a statement in shell script like this
BASEDIR=`cd ../;pwd`
But have no idea how to do that. I know that %CD% will give me current directory but i want to set one directory up path in variable . Please help.
A bit more complex as in shell code.
FOR /F "delims=" %%A in ("%CD%\..") do set "basedir=%%~fA"
Edit related to your comment:
To replace \ with \\ just add the line
set "basedir=%basedir:\=\\%"
Another way...
pushd ..
set "BaseDir=%CD%"
popd
for /f "delims=" %%a in ("%cd%") do set "upper_dir=%%~dpa"
Consider:
#echo off
set "dir=C:\Windows\System32"
call:up %dir%
:up
echo/%~dp1

Windows Batch help in setting a variable from command output [duplicate]

This question already has answers here:
Set output of a command as a variable (with pipes) [duplicate]
(6 answers)
Closed 7 years ago.
I need to run a simple find command and redirect the output to a variable in a Windows Batch File.
I have tried this:
set file=ls|find ".txt"
echo %file%
But it does not work.
If I run this command it works without problems:
set file=test.txt
echo %file%
So obviously my command output is not being set to my variable. Can anyone help? Thanks
I just find out how to use commands with pipes in it, here's my command (that extracts the head revision of an svn repo) :
SET SVN_INFO_CMD=svn info http://mySvnRepo/MyProjects
FOR /f "tokens=1 delims=" %%i IN ('%SVN_INFO_CMD% ^| find "Revision"') DO echo %%i
First of all, what you seem to expect from your question isn't even possible in UNIX shells. How should the shell know that ls|find foo is a command and test.txt is not? What to execute here? That's why UNIX shells have the backtick for such things. Anyway, I digress.
You can't set environment variables to multi-line strings from the shell. So we now have a problem because the output of ls wouldn't quite fit.
What you really want here, though, is a list of all text files, right? Depending on what you need it's very easy to do. The main part in all of these examples is the for loop, iterating over a set of files.
If you just need to do an action for every text file:
for %%i in (*.txt) do echo Doing something with "%%i"
This even works for file names with spaces and it won't erroneously catch files that just have a .txt in the middle of their name, such as foo.txt.bar. Just to point out that your approach isn't as pretty as you'd like it to be.
Anyway, if you want a list of files you can use a little trick to create arrays, or something like that:
setlocal enabledelayedexpansion
set N=0
for %%i in (*.txt) do (
set Files[!N!]=%%i
set /a N+=1
)
After this you will have a number of environment variables, named Files[0], Files[1], etc. each one containing a single file name. You can loop over that with
for /l %%x in (1,1,%N%) do echo.!Files[%%x]!
(Note that we output a superfluous new line here, we could remove that but takes one more line of code :-))
Then you can build a really long line of file names, if you wish. You might recognize the pattern:
setlocal enabledelayedexpansion
set Files=
for %%i in (*.txt) do set Files=!Files! "%%i"
Now we have a really long line with file names. Use it for whatever you wish. This is sometimes handy for passing a bunch of files to another program.
Keep in mind though, that the maximum line length for batch files is around 8190 characters. So that puts a limit on the number of things you can have in a single line. And yes, enumerating a whole bunch of files in a single line might overflow here.
Back to the original point, that batch files have no way of capturing a command output. Others have noted it before. You can use for /f for this purpose:
for /f %%i in ('dir /b') do ...
This will iterate over the lines returned by the command, tokenizing them along the way. Not quite as handy maybe as backticks but close enough and sufficient for most puposes.
By default the tokens are broken up at whitespace, so if you got a file name "Foo bar" then suddenly you would have only "Foo" in %%i and "bar" in %%j. It can be confusing and such things are the main reason why you don't ever want to use for /f just to get a file listing.
You can also use backticks instead of apostrophes if that clashes with some program arguments:
for /f "usebackq" %%i in (`echo I can write 'apostrophes'`) do ...
Note that this also tokenizes. There are some more options you can give. They are detailed in the help for command.
set command has /p option that tells it to read a value from standard input. Unfortunately, it does not support piping into it, but it supports reading a value from a first line of existing file.
So, to set your variable to the name of a first *.txt file, you could do the following:
dir /b *.txt > filename.tmp
set /p file=< filename.tmp
del /q filename.tmp
It is important not to add a space before or even after =.
P. S. No fors, no tokens.
Here's a batch file which will return the last item output by find:
#echo off
ls | find ".txt" > %temp%\temp.txt
for /f %%i in (%temp%\temp.txt) do set file=%%i
del %temp%\temp.txt
echo %file%
for has a syntax for parsing command output, for /f "usebackq", but it cannot handle pipes in the command, so I've redirected output to a temporary location.
I strongly recommend, given that you have access to ls, that you consider using a better batch language, such as bash or even an scripting language like python or ruby. Even bash would be a 20x improvement over cmd scripting.
The short answer is: Don't!
A windows shell env var can hold a max of 32 Kb and it isn't safe to save output from programs in them.
That's why you can't. In batch script you must adopt another programming style. If you need all of the output
from the program then save it to file. If you only need to check for certain properties then pipe the output into
a program that does the checking and use the errorlevel mechanism:
#echo off
type somefile.txt | find "somestring" >nul
if %errorlevel% EQU 1 echo Sorry, not found!
REM Alternatively:
if errorlevel 1 echo Sorry, not found!
However, it's more elegant to use the logical operators Perl style:
#echo off
(type somefile.txt | find "somestring" >nul) || echo Sorry, not found!
It's not available in DOS, but in the Windows console, there is the for command. Just type 'help for' at a command prompt to see all of the options. To set a single variable you can use this:
for /f %%i in ('find .txt') do set file=%%i
Note this will only work for the first line returned from 'find .txt' because windows only expands variable once by default. You'll have to enable delayed expansion as shown here.
what you are essentially doing is listing out .txt files. With that, you can use a for loop to over dir cmd
eg
for /f "tokens=*" %%i in ('dir /b *.txt') do set file=%%i
or if you prefer using your ls, there's no need to pipe to find.
for /f "tokens=*" %%i in ('ls *.txt') do set file=%%i
Example of setting a variable from command output:
FOR /F "usebackq" %%Z IN ( `C:\cygwin\bin\cygpath "C:\scripts\sample.sh"` ) DO SET BASH_SCRIPT=%%Z
c:\cygwin\bin\bash -c '. ~/.bashrc ; %BASH_SCRIPT%'
Also, note that if you want to test out the FOR command in a DOS shell, then you need only use %Z instead of %%Z, otherwise it will complain with the following error:
%%Z was unexpected at this time.

Resources