I have the following Batch script which replaces occurrences of {path} in a text file with a path:
#echo off
setlocal EnableDelayedExpansion
set myPath=C:\Program Files (x86)\foo
for /F "tokens=*" %%A in (template.txt) do (
set line=%%A
set line=!line:{path}=%myPath%!
echo !line!
)
When I run this script I get the error message
\foo! was unexpected at this time.
If I remove the parentheses in the path it works as expected. How can I solve this problem? I cannot have quotes around the path in the text file so putting quotes around the path in the set statement is not an option.
#echo off
setlocal EnableDelayedExpansion
set "mypath=C:\Program Files (x86)\foo"
for /F "tokens=*" %%A in (q71593680.txt) do (
set "line=%%A"
CALL :changeline
echo !line!
)
FOR %%c IN ("%mypath%") DO for /F "tokens=*" %%A in (q71593680.txt) do (
set "line=%%A"
set "line=!line:{path}=%%~c!"
echo !line!
)
GOTO :EOF
:changeline
set "line=!line:{path}=%mypath%!"
GOTO :eof
The problem is that the ) in the substitution-string is being taken as the closing parenthesis of the do.
Solution : make an internal subroutine as shown.
Use set "var1=data" for setting string values - this avoids problems caused by trailing spaces.
Don't use path as a variablename - it's a reserved word in batch, meaning the sequence in which the directories are searched to find an executable that isn't in the current directory.
Use set path=%ProgramFiles(x86)%\foo first (this folder may be elsewhere, this variable is here to find it anyway), and surround the replacement set with quotes (see below).
Corrected program:
#echo off
setlocal EnableDelayedExpansion
set pathval=%ProgramFiles(x86)%\foo
for /F "tokens=*" %%A in (template.txt) do (
set line=%%A
REM Please note the quotes around the affectation. It avoids an interpretation.
set "line=!line:{path}=%pathval%!"
echo !line!
)
Side note: even with setlocal, avoid to name a variable path...
Related
The file is not added in the destination path if it has spaces in the file name.
For example, if the filename is textfile1.txt -> it will be added in the destination path. However, if the directory filename has space like this text file4.txt it will not be added.
Is there a way to remove the spaces of the filename?
Here is the image:
Here is my main concern:
Here is my script:
#ECHO off
TITLE (c) ASDG
SETLOCAL EnableDelayedExpansion
SET locationPath=C:\Textfiles\
SET destinationPath=E:\Textfiles\
SET status=success
SET countMetadata=0
SET countPDF=0
SET countJPEG=0
ECHO Executing the program...
FOR /R %locationPath% %%g IN (*.txt) DO (
CD %%~dpg
IF EXIST *.txt* (
FOR /F "skip=1 tokens=1* delims=|" %%a IN (%%~nxg) DO (
SET /a countMetadata+=1
ECHO %%~dpa%%a^| %%b >> %destinationPath%^%%~nxg
)
IF %status% == success (
ECHO %%g has been successfully added
ECHO %%g >> %destinationPath%^logs.txt
)
)
)
After reformatting to use indentation to show code blocks (parenthesised code that is parsed, substituting %variables%, then executed), I then applied various recommendations:
Use set "var=value" for setting string values - this avoids problems caused by trailing spaces. Don't assign " or a terminal backslash or Space. Build pathnames from the elements - counterintuitively, it is likely to make the process easier. If the syntax set var="value" is used, then the quotes become part of the value assigned.
Use set /a to assign numeric values. No quotes required.
THIS CODE WILL NOT FULLY PERFORM THE REQUIRED TASK
Without comments to explain why some code is used, it's difficult to provide guidance.
#ECHO OFF
SETLOCAL EnableDelayedExpansion
TITLE (c) ASDG
SET "locationPath=C:\Textfiles"
SET "destinationPath=E:\Textfiles"
SET "status=success"
SET /a countMetadata=0
SET /a countPDF=0
SET /a countJPEG=0
ECHO Executing the program...
FOR /R "%locationPath%" %%g IN (*.txt) DO (
CD %%~dpg
IF EXIST *.txt* (
FOR /F "usebackq skip=1 tokens=1* delims=|" %%a IN ("%%~nxg") DO (
SET /a countMetadata+=1
ECHO %%~dpa%%a^| %%b >> %destinationPath%\%%~nxg
)
IF !status! == success (
ECHO %%g has been successfully added
ECHO %%g >> %destinationPath%\logs.txt
)
)
)
GOTO :EOF
Modifications explanation
I prefer the setlocal to be the second line. YMMV.
Set commands modified as explained above
locationpath in the for /R quoted - it may contain separators like spaces.
%%~nxg quoted in for...%%a as it may contain spaces
usebackq added to for...%%a as %%~nxg is now quoted
I prefer to avoid ADFNPSTXZ (in either case) as metavariables (loop-control variables)
ADFNPSTXZ are also metavariable-modifiers which can lead to difficult-to-find bugs
(See `for/f` from the prompt for documentation)
Not sure what is going on with the following echo, but destinationPath no longer has the terminal \. Same comment applies to the following ECHO %%g.
!staus! replaces %status% (logically) as logically, status may change within the block - the delayed expansion trap
BUT status is not being varied within the block, so its value will always be its initial value, success.
Using Boolean
So - a few things for OP to clean up...
I've written a batch file to modify the attribute of an XML file. The script works and the attribute if modified, however I'm having an issue with escaping some characters.
I've tried every solution I can possibly find online with no luck.
My intended output is:
<xs:import schemaLocation="2e9dd7db-f58b-4c91-8575-3b3af05d3178.xsd" namespace="urn:verastar:veracore:types" />
However I'm getting:
<xs:import schemaLocation="="2e9dd7db-f58b-4c91-8575-3b3af05d3178.xsd"" namespace="urn:verastar:veracore:types
I've tried escaping the quotes with ^, this works when using echo to the console however doesn;t work when writing to the file.
Why am I getting ="=" also I'm getting double quotes, but when I remove one nothing gets written to the file.. and finally the last quote seems to be messing things up and therefore the output is missing the XML closing tag.
How can I escape these characters properly?
My code is:
#echo on
setlocal EnableExtensions DisableDelayedExpansion
rem check if the XSD to modify exists in the batch directory
set "XSDFile=%~dp0test.xsd"
if not exist "%XSDFile%" goto EndBatch
rem environment variables
set "LineNumber="
set "LineCount=0"
set "TmpFile=%TEMP%\%~n0.tmp"
rem Search for the line containing attribute schemaLocation and get its
rem line number and the line itself loaded into environment variables
for /F "tokens=1* delims=:" %%I in ('%SystemRoot%\System32\findstr.exe /L /N /C:schemaLocation= "%XSDFile%" 2^>nul') do (
set "LineNumber=%%I"
set "FileLine=%%J"
)
rem If no line with attribute schemaLocation found, exit this batch file
if not defined LineNumber goto EndBatch
setlocal EnableDelayedExpansion
set "FileName=!FileLine:*schemaLocation=!"
for /f "tokens=1 delims=?" %%a in ("%FileName%") do (set test=%%a)
set "test=<xs:import schemaLocation="%test%.xsd"" namespace="urn:verastar:veracore:types" />"
pause
endlocal & set "FileLine=%test%
rem Make sure the temporary file used next does not already exist.
del "%TmpFile%" 2>nul
rem Copy all lines from XML file to a temporary file including empty
rem lines with the exception of the line containing attribute schemaLocation
rem which is copied to temporary file with the modified schemaLocation.
for /F "tokens=1* delims=:" %%I in ('%SystemRoot%\System32\findstr.exe /R /N "^" "%XSDFile%" 2^>nul') do (
set "XmlLine=%%J"
set /A LineCount+=1
setlocal EnableDelayedExpansion
if not !LineCount! == %LineNumber% (
echo/!XmlLine!>>"%TmpFile%"
) else (
echo/!FileLine!>>"%TmpFile%"
)
endlocal
)
rem Overwrite original file with temporary file automatically deleted on success.
move /Y "%TmpFile%" "%XSDFile%" >nul
:EndBatch
endlocal
I'm working on a DOS script in order to search a line and replace it into files from a specific folder. Here is what i have already done :
#echo off
setlocal enableextensions disabledelayedexpansion
set "search=#Interceptors({ RuntimeExceptionInterceptor.class }^)"
set "replace=#Interceptors({ RuntimeExceptionInterceptor.class, ReportInterceptor.class, CorrelationIdInterceptor }^)"
set "textFile=C:\Utilisateurs\a669884\Documents\test.txt"
for %%a in (*.txt) do (
echo "%%a"
for /f "Delims=" %%i in (%%a ^& break ^> %%a) do (
set "line=%%i "
setlocal enabledelayedexpansion
>>%%a echo(!line:%search%=%replace%!
endlocal
)
)
Problem is that my first line is not replace by the new one, the new line is added under it like that :
#Interceptors({ RuntimeExceptionInterceptor.class })
#Interceptors({ RuntimeExceptionInterceptor.class, ReportInterceptor.class, CorrelationIdInterceptor })
Do you know why my first line isn't replaced? Thanks a lot
Seb
Not sure what setting textfile has to do with the routine - it's not used.
Your original code produced a complaint that & was not found and created an empty file for me.
Changing the for to
for /f "Delims=" %%i in ('type "%%a" ^& break ^> "%%a"') do (
seemed to make the substitution, given the one line (partial?) of sourcefile you've provided, plus a few dummy lines.
execute the type... with the filenames enclosed in quotes to ensure correct operation with separators, replacing the file; substitute as specified.
I'm manipulating some HTML via Batch. I'm using delayed expansion but when a semicolon is encountered inside double quotes, the script fails to copy anything after and including the semicolon.
It's probably due to the fact that I use double quotes when I pass the variable to the putLineInHTMLFile label (I need to keep things separated in labels).
#echo off
setlocal enableDelayedExpansion
del output.html
for /f "delims=" %%x in (file.html) do call :putLineInHTMLFile "%%x"
goto :EOF
:putLineInHTMLFile
set "line=%~1"
echo !line!>> output.html
file.html contains:
<tag1>
<tag"bla;2">
After running the script, output.html contains:
<tag1>
<tag"bla
I've tried escaping the semicolon with ^ or ^^. Didn't work. I've tried escaping the double quotes too. That didn't work either.
I can change the contents of file.html anyway I please just as long as I can include that semicolon in the output file.
This seems to work for the test-case given; no guarantees for wider use:
#echo off
setlocal enableDelayedExpansion
del output.html
for /f "delims=# tokens=*" %%x in (file.html) do (
set "safe=%%x"
set "safe=!safe:"=""!"
call :putLineInHTMLFile "!safe!"
)
goto :eof
:putLineInHTMLFile
set "line=%~1"
set "line=%line:""="%"
echo !line!>> output.html
:eof
Within the "body" of the for command, the %%x has not been split, it's only when processed by the call command that this happens. To protect that, I've used safe to double-up all double-quotes in the string, and then added a line in the subroutine to strip them out again.
This doesn't work properly if the double-quotes aren't matched, but in those cases, neither does the echoing of the trailing >, even when there are no semi-colons present.
This method works in all cases, as long as the quotes be matched (even number) in the input lines:
#echo off
setlocal enableDelayedExpansion
del output.html
for /f "delims=" %%x in (file.html) do call :putLineInHTMLFile "%%x"
goto :EOF
:putLineInHTMLFile
set line=%*
echo !line:~1,-1!>> output.html
PS - Please, do not include additional parts that not appears in the original code, like the :eof label... The label is written in uppercase letters in goto :EOF command to indicate that it is special. Type goto /? for further details.
Certainly. The problem is that the subroutine receives
"<tag"bla;2">"
for that line. The parser sees that as
Token1 : "<tag"bla
Token2 : 2">"
because ; like Space is a separator.
Sadly, without knowing what you intend to do within the subroutine, it's difficult to advise on how to circumvent the problem.
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q43391363.txt"
SET "outfile=%destdir%\outfile.txt"
SET "outfile2=%destdir%\outfile2.txt"
del "%outfile%"
del "%outfile2%"
(for /f "delims=" %%x in (%filename1%) do set "line=%%x"&call :putLineInHTMLFile "%%x")>"%outfile2%"
goto :eof
:putLineInHTMLFile
ECHO %*
echo !line!>>"%outfile%"
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
I used a file named q43391363.txt containing your data for my testing.
Produces files defined as %outfile% and %outfile2%
So - here's two different ways, one using conventional output direct to outfile1 and the other using redirection from a subroutine into outfile2.
I want to be able to replace a line in a properties file but i only know part of the line string at any one time
Heres the line i want to replace: mb.datasource.password=ENC(8dF45fdD)
with this: mb.datasource.password=apassword
What i have just now is this
#echo off &setlocal
set "search=mb.datasource.password="
set "replace=mb.datasource.password=apassword"
set "textfile=mb.properties"
set "newfile=mb-new.properties"
(for /f "delims=" %%i in (%textfile%) do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:%search%=%replace%!"
echo(!line!
endlocal
))>"%newfile%"
This ends up giving me mb.datasource.password=apassword=ENC(8fFdeUdK)
I can't just find the full string it needs to only be mb.datasource.password= because the part after the equals changes
Any help would be greatly appreciated?
You can do it with batch. I put together a quick script and it worked for me:
#ECHO OFF
SETLOCAL EnableExtensions
SET SourceFile="mb.properties"
SET OutputFile="mb-new.properties"
SET "FindKey=mb.datasource.password"
SET "NewValue=apassword"
REM Basic parse for INI file format.
(FOR /F "usebackq eol= tokens=1,* delims==" %%A IN (`TYPE %SourceFile%`) DO (
REM If the key value matches, build the line with the new value.
REM Otherwise write out the existing value.
IF /I "%%A"=="%FindKey%" (
ECHO %%A=%NewValue%
) ELSE (
ECHO %%A=%%B
)
)) > %OutputFile%
REM Replace old with new.
DEL %SourceFile%
MOVE %OutputFile% %SourceFile%
ENDLOCAL
A few notes about the above:
I assumed basic INI file format.
The FOR loop will skip blank lines so they would be removed from the new output file. There are ways around this using tricks with the FIND command if the blanks are needed.
If you have special chars (% or ! especially) - this may cause some problems, but if you have just "normal" text then it should be fine.