#echo off
setlocal enableextensions disabledelayedexpansion
for /r %f in (xis_a*) do More +1 %~nxf >> No_header_%~nxf
set "search=:20:"
set "replace={:20:"
for /f "delims=" %%i in ('type (No_header_*.txt) ^& break ^> (No_header_*.txt) ') do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:%search%=%replace%!"
>>No_header_*.txt echo(!line!
endlocal
)
am trying to skip the header line in a text file and replace :20: with {:20:. i have written and have achieved almost.. please try to help me am totally new to this
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
set "search=:20:"
set "replace={:20:"
for /r "%sourcedir%" %%f in (xis_a*) do (
REM DEL "%destdir%\No_header_%%~nf.txt" >NUL 2>nul
for /f "usebackqskip=1delims=" %%i in ("%%f") do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:%search%=%replace%!"
>>"%destdir%\No_header_%%~nf.txt" echo(!line!
ENDLOCAL
)
)
GOTO :EOF
This should solve the problem.
In your code, the initial setlocal is establishing the default condition, so I omitted it.
You have %f in your 'for /r - the % before the metavariable f needs to be doubled.
The more ceremony isn't required - for /f has a skip option which will allow the first n lines to be skipped.
So - all that is required is to get the list of files generated by the for...%%f... loop and with each, process each individual file, skipping the first line. Quoting the filename appearing in %%f is simply a safety-measure to allow for filenames containing separators, but this means that usebackq needs to be invoked to tell for /f that the list given is not a literal string (which it will assume for a "quoted string,") but a filename.
Then, since %%f is in-context for the %%i loop, you can select the target filename by using %%~nf. I'm not sure whether you want ~nf or ~nxf (adding a second .txt extension) so I elected to use ~n alone. Note that your use of * is doomed - that means "all files matching" - probably not quite what you want, and cmd will get very confused.
I've aded a remmed-out del command to allow the destination file to be deleted - just remove the rem if required, otherwise the data will be appended to any exiating file.
I use my u: drive for testing, and have left my source and destination names in place. No doubt you would need to change those to suit your system.
Related
I'm trying to extract every value for FileRef from a string I've already extracted out of a file. Unfortunately, the string is one line which makes it more difficult to use for /f "tokens=*".
The string is:
"<Cim:TrnTable_list><Cim:TrnTable Id="Root"><Cim:TrnElem Ref="3" FileRef="A1-FS.elt"/><Cim:TrnElem Ref="4" FileRef="A1-MS.elt"/><Cim:TrnElem Ref="9" FileRef="Product\Product-v1\Product-v1-MD.elt"/><Cim:TrnElem Ref="11" FileRef="Product\Product-v2\Product-v2-MD.elt"/><Cim:TrnElem Ref="12" FileRef="RunnerPart_Assembly#1.elt"/></Cim:TrnTable></Cim:TrnTable_list>"
How to get every value for FileRef inserted into a variable in the following format?:
A1-FS.elt?A1-MS.elt?Product\Product-v1\Product-v1-MD.elt?Product\Product-v2\Product-v2-MD.elt?RunnerPart_Assembly#1.elt
I mean, then I could loop trough them using for /f "delims=?" right?
Or is there a way to convert each ? in the above example to a 'new line' within one string, or maybe even better ideas to loop trough each FileRef-value?
Many thanks!
Squashman is right in his comment, use a language that is capable of handling XML data natively.
Anyway, if you insist on using pure Windows batch scripting, you could assemble a new string with ? symbols as separator like in the following script:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILE=%~dpn0.txt" & rem // (path to file containing the line of text)
(set ^"_LF=^
%= empty line =%
^") & rem // (this constitutes a new-line character)
rem // Initialise collection variable:
set "COLL=?"
rem // Read line from file:
for /F "usebackq delims=" %%L in ("%_FILE%") do (
set "LINE=%%~L"
setlocal EnableDelayedExpansion
rem // Replace `><` by `>` + line-break + `<`:
set ^"LINE=!LINE:^>^<=^>^%_LF%%_LF%^<!^"
rem // Read one tag enclosed within `<` and `>`:
for /F "delims=" %%I in ("!LINE!") do (
endlocal
set "ITEM=%%I"
rem // Extract string between ` FileRef` and `/>`:
setlocal EnableDelayedExpansion
set "ITEM=!ITEM:* FileRef=!"
set "ITEM=!ITEM:/>=!"
rem // Check for `=`-sign after `FileRef`:
if "!ITEM:~,1!"=="=" (
rem // Remove leading `=` and surrounding `""`:
for /F "delims=| eol=|" %%F in ("!ITEM:~1!") do (
endlocal
set "NAME=%%~F"
rem // Assemble return string using `?` as separator:
setlocal EnableDelayedExpansion
for /F "delims=| eol=|" %%J in ("!COLL!!NAME!?") do (
endlocal
set "COLL=%%J"
setlocal EnableDelayedExpansion
)
)
)
)
endlocal
)
rem // Return collection variable:
setlocal EnableDelayedExpansion
echo(!COLL:~1,-1!
endlocal
endlocal
exit /B
Toggling delayed expansion is done in order not to have trouble with ! symbols.
Better than collecting all values in a single variable is to just loop through them in my opinion.
This is one other way to brute force this. This code will put each FileRef into its own variable and sequence the variable name up.
#echo off
FOR /F "delims=" %%G IN (line.txt) do set "line=%%G"
set i=0
:loop
set /a i+=1
set "line=%line:*FileRef=%"
FOR /F "tokens=1* delims==/" %%G IN ("%line%") DO (
set "var%i%=%%~G"
set "line=%%H"
)
echo "%line%"|find /I "fileref" >nul 2>&1 &&GOTO loop
set var
pause
When executed it will output this.
C:\BatchFiles\SO\XML>bruteforce.bat
var1=A1-FS.elt
var2=A1-MS.elt
var3=Product\Product-v1\Product-v1-MD.elt
var4=Product\Product-v2\Product-v2-MD.elt
var5=RunnerPart_Assembly#1.elt
Press any key to continue . . .
If you don't want the data assigned into their own individual variables you can just use the %%G meta-variable directly inside the FOR command.
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 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.
I am trying to write a batch file to find and replace a string in multiple files within a folder. But I am getting this error:
Cannot perform a cyclic copy
Any idea why that happens?
#echo off
SETLOCAL
for %%* in (.) do set foldername=%%~n*
SET stringtofindreplace=XXXX
for %%f in (*.fmw) do (
echo Processing %%f...
fOR /F "delims=" %%l IN (%%f) DO (
SET "line=%%l"
SETLOCAL ENABLEDELAYEDEXPANSION
set "x=!line:%stringtofindreplace%=%foldername%!"
echo(!x!
ENDLOCAL)
)>%%~nf.new
)
GOTO:EOF
#ECHO OFF
SETLOCAL
:: no idea what this is aimed at doing...??
for %%* in (.) do set new=%%~n*
SET new=newstring
SET old=XXXX
for %%f in (*.fmw) do (
echo Processing %%f...
(
FOR /F "delims=" %%l IN (%%f) DO (
SET "line=%%l"
SETLOCAL ENABLEDELAYEDEXPANSION
set "x=!line:%old%=%new%!"
ECHO(!x!
ENDLOCAL
)
)>%%~nf.new
)
GOTO :EOF
I've no idea what you are trying to do with the first for, so I just made an obvious replacement string.
You need to add the "delims=" option to deliver the entire line to %%l.
Make sure there are no trailing spaces on the ECHO(!x!
This will make a new file called *.new from each *.fmw file.
Cannot perform a cyclic copy error occurs when the source folder includes the target folder, and so is trying to copy all the files, including the files it has already copied.
This will give you that error.
xcopy c:\apple\*.* c:\apple\backup\ /s
I need to get all the filenames in a directory and store them in some variable from a command line.
I came across this
`dir /s /b > print.txt`
but this prints the file names to a txt file.
How can I store these names in a variable?
I'm assuming you really mean Windows batch file, not DOS.
Batch environment variables are limited to 8191 characters, so likely will not be able to fit all the file paths into one variable, depending on the number of files and the average file path length.
File names should be quoted in case they contain spaces.
Assuming they fit into one variable, you can use:
#echo off
setlocal disableDelayedExpansion
set "files="
for /r %%F in (*) do call set files=%%files%% "%%F"
The CALL statement is fairly slow. It is faster to use delayed expansion, but expansion of %%F will corrupt any value containing ! if delayed expansion is enabled. With a bit more work, you can have a fast and safe delayed expansion version.
#echo off
setlocal disableDelayedExpansion
set "files=."
for /r %%F in (*) do (
setlocal enableDelayedExpansion
for /f "delims=" %%A in ("!files!") do (
endlocal
set "files=%%A "%%F"
)
)
(set files=%files:~2%)
If the file names do not fit into one variable, then you should resort to a pseudo array of values, one per file. In the script below, I use FINDSTR to prefix each line of DIR ouptut with a line number prefix. I use the line number as the index to the array.
#echo off
setlocal disableDelayedExpansion
:: Load the file path "array"
for /f "tokens=1* delims=:" %%A in ('dir /s /b^|findstr /n "^"') do (
set "file.%%A=%%B"
set "file.count=%%A"
)
:: Access the values
setlocal enableDelayedExpansion
for /l %%N in (1 1 %file.count%) do echo !file.%%N!
As #Matt said, use a batch file.
setlocal enabledelayedexpansion
set params=
for /f "delims=" %%a in ('dir /s/b') do set params=!params! %%a
setlocal enableDelayedExpansion
set /a counter=0
for /f %%l in ('dir /b /s') do (
set /a counter=counter+1
set line_!counter!=%%l
)
set line_
If you want to store all in one variable check this:
Explain how dos-batch newline variable hack works