Write batch variable into specific line in a text file - text

I have a batch file where I need to write a variable into a specific line of a text file and override what is all ready in that line. I have the code to read specific lines from the file maybe I could switch it around to also write?
Reading lines code:
setLocal EnableDelayedExpansion
for /f "tokens=* delims= " %%a in (variables.txt) do (
set /a N+=1
set v!N!=%%a
)
set variable1=!v1!
set variable2=!v2!
set variable3=!v3!
set variable4=!v4!
I've tried to add echo %variable1% > !v4! something like that but it doesn't work.

I figured it out!! Here is the code for anyone else who might ever need it.
#echo off
setlocal enableextensions enabledelayedexpansion
set inputfile=variables.txt
set tempfile=%random%-%random%.tmp
copy /y nul %tempfile%
set line=0
for /f "delims=" %%l in (%inputfile%) do (
set /a line+=1
if !line!==4 (
echo WORDS YOU REPLACE IT WITH>>%tempfile%
) else (
echo %%l>>%tempfile%
)
)
del %inputfile%
ren %tempfile% %inputfile%
endlocal

Another option might be to overwrite the file entirely. Here's the part to do that:
:saveVars
(
ECHO %v1%
ECHO %v2%
ECHO %v3%
ECHO %v4%
ECHO %v5%
) >variables.txt
GOTO :EOF
That is, if the number of lines is fixed and known beforehand. If not, you might want to store the last value of the increment in your example code and, when saving the variables, use it like this:
:saveVars
SETLOCAL EnableDelayedExpansion
(
FOR /L %%i IN (1,1,%N%) DO (ECHO !v%%i!)
) >variables.txt
ENDLOCAL
GOTO :EOF
I'm assuming here that the v1/v2 etc. variables would be used only for synchronising with the file: when it is read, the lines are stored in those variables, and when any of them (variables) gets changed, you just call the saveVars subroutine immediately. Here's an example how you would use it:
…
SET v2=something
CALL :saveVars
…
SET v4=%somevar%
CALL :saveVars
…
If the file is small, the rewriting should be fast enough.

Not absolutely sure I've understood everything correctly, but if you want to substitute something for an existing part of a text file with a batch script, you'll need to write everything (including the changed part) to a new file first, then delete the original and rename the new file to the original name.
I can't really see a point of reading everything into variables, unless I'm missing something. You could simply iterate over the lines writing them one by one into the new file and replacing the specific line's contents with the substitute text along the way:
setLocal EnableDelayedExpansion
>newFile.txt (
for /f "tokens=* delims= " %%a in (variables.txt) do (
set /a N+=1
if !N! == 4 (ECHO substitute text) ELSE ECHO %%a
)
)
del variables.txt
rename newFile.txt variables.txt
If the substitute text must, in turn, be derived from one of the lines, you could do something like this:
setLocal EnableDelayedExpansion
>newFile.txt (
for /f "tokens=* delims= " %%a in (variables.txt) do (
set /a N+=1
if !N! == 1 SET subst_text=%%a
if !N! == 4 (ECHO !subst_text!) ELSE ECHO %%a
)
)
del variables.txt
rename newFile.txt variables.txt

Related

Manipulation on delayed expansion string variable is failing

I am trying to find a particular line from an XML file and extract the value using string manipulation operations.
Below is the code I am trying.
#echo off
setlocal enabledelayedexpansion
::Expected line is "<filename>c:\temp\file1</filename>"
for /f "tokens=*" %%i in ('findstr /i "filename" file1.props') do (
SET LINE=%%i
)
echo !LINE!
SET FILENAME=!LINE:<filename>=!
SET FILENAME=%FILENAME:</filename>=%
ECHO !FILENAME!
And the output is:
<filename>c:\temp\file1</filename>
The system cannot find the file specified.
ECHO is off.
I actually want this value c:\temp\file1
Someone please help me correct the code or please suggest any other simpler way.
The problem is the execution of set. The parser interprets the > and < as redirection, so it will fail with a syntax error. Use quotes to process it as intended (`set "var=value"):
#echo off
setlocal enabledelayedexpansion
REM echo ^<filename^>c:\temp\file1^</filename^>>file1.props
::Expected line is "<filename>c:\temp\file1</filename>"
for /f "tokens=*" %%i in ('findstr /i "filename" file1.props') do (
SET "LINE=%%i"
)
echo !LINE!
SET "FILENAME=!LINE:<filename>=!"
SET "FILENAME=%FILENAME:</filename>=%"
ECHO !FILENAME!
Output is:
<filename>c:\temp\file1</filename>
c:\temp\file1

batch file to remove a column in csv

I wrote this code so I can remove a column from a csv file.
#echo off
setlocal enableextensions enabledelayedexpansion
type nul > tmp.txt
SET /A COUNT=0
for /F "tokens=*" %%A in (d.csv) do (
set LINE="%%A"
set /A COUNT+=1
for /F "tokens=1,2,3,4,5,6,7,8,* delims=," %%a in (!LINE!) do (
set row[0]=%%a
set row[1]=%%b
set row[2]=%%c
set row[3]=%%d
set row[4]=%%e
set row[5]=%%f
set row[6]=%%g
set row[7]=%%h
)
echo !row[0]!,!row[2]!,!row[3]!,!row[4]!,!row[5]!,!row[6]! >>tmp.txt
echo.
)
endlocal
Test file:
A1,B1,C1,D1,la la,,1
A2,B2,C2,D2, ,fef 3,
A3,B3,C3,D3,be be ,bo,bo 1
A4,B4,C4,D4,tu tu,tu 7,881
Output file:
A1,C1,D1,la la,1,
A2,C2,D2, ,fef 3,
A3,C3,D3,be be ,bo,bo 1
A4,C4,D4,tu tu,tu 7,881
I don't get why in the output file at the first line the ,, is eliminated and a , added at the end. Also I am wondering if there is a better way to do this.
Thanks!
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
(
FOR /f "delims=" %%a IN (q29441490.txt) DO (
SET "line=%%a"
SET "line=!line:,= , !"
FOR /f "tokens=1,2*delims=," %%p IN ("!line!") DO (
SET "line=%%p,%%r"
SET "line=!line: , =,!"
ECHO(!line!
)
)
)>u:\newfile.txt
GOTO :EOF
I used a file named q29441490.txt containing your data for my testing.
Produces u:\newfile.txt
the separators between tokens are delimiter sequences, so ,, is seen as one separator, hence the fields appear moved by one place.
Grab each line, replace each , with , tokenise (you don't say explicitly, but you appear to want to eliminate the second column) so %%q gets the first column and %%r the remainder of the line following the second. Concatenate these, insert the comma and then reverse the substitution.
If you wanted to eliminate another column, then a different tokens element should be specified and the restructure of the line would need to be adjusted.

Batch Script - Find words that contain a certain string withing a file

I have a file with a lot of text.
EG
Hello
This is my file
this is the end of the file
I need a script that will search the file and pull out all words (just the words and not the line into another file) that contain for example the letter e
In this case the new file would look like
Hello
file
the
end
the
file
It may also need to search for as another example bh. (including the full stop) so a file with the following
hello
bh.ah1
my file
the end
would produce a file with
bh.ah1
hope this is enough detail
#ECHO OFF
SETLOCAL
SET "target=%~1"
FOR /f "delims=" %%a IN (q22560073.txt) DO CALL :findem %%a
GOTO :EOF
:findem
SET candidate=%1
IF NOT DEFINED candidate GOTO :EOF
ECHO %1|FIND /i "%target%" >NUL
IF NOT ERRORLEVEL 1 ECHO(%1
shift
GOTO findem
I used a file named q22560073.txt for my testing.
To find the text string, use
thisbatch text
so
thisbatch e
would find the first list and
thisbatch bh.
the second.
(I combined both sample testfiles as q22560073.txt)
the /i in the find command makes the test case-insensitive.
To output to a file, simply use
thisbatch text >"filename"
where the "rabbits ears" are only required if the filenames contains spaces and other problematic characters, but do no harm in any case.
This should work for a target of any alphabetic or numeric combination plus full stop. It will not work with characters that have a special meaning to cmd.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "target=%~1"
FOR /f "delims=" %%a IN (q22560073.txt) DO (
SET "line=%%a"
SET "line=!line:(= !"
SET "line=!line:)= !"
CALL :findem !line!
)
GOTO :EOF
:findem
SET candidate=%1
IF NOT DEFINED candidate GOTO :EOF
ECHO %1|FIND /i "%target%" >NUL
IF NOT ERRORLEVEL 1 ECHO(%1
shift
GOTO findem
revised on further information.
#echo off
set "searchfor=bh."
for /f "delims=" %%i in (t.t) do (
for %%j in (%%i) do (
echo %%j|find "%searchfor%" >nul && echo %%j
)
)
for every line (%%i) do
for every word in this line (%%j) do
if searchstring found then echo word
EDIT to your comment: replace the ( with a space in the line, before processing words
#echo off
setlocal enabledelayedexpansion
set "searchfor=bh."
for /f "delims=" %%i in (t.t) do (
set t=%%i
set t=!t:(= !
for %%j in (!t!) do (
echo %%j|find "%searchfor%" >nul && echo %%j
)
)
You can do this for more characters with additional lines like set t=!t:(= ! (replace ( with )

A Batch file to read a file and replace a string with a new one

I want to create a batch file to read every line of a file in a loop and replace a string with another one. Following is my code snippet:
for /F "tokens=*" %%i in (myfile) do (
set str=%%i
set str=%str: %oldstring% = %newstring%%
echo %str% >> newfile
)
This results in a newfile with 'Echo is off' as many lines as there are in myfile. Seems like str variable holds no value at all when assigned to %%i. Can someone help me?
Try out this small script:
#echo off
set val=50
echo %val%
for /l %%i in (1,1,1) do (
set val=%%i
echo %val%
)
echo %val%
pause>nul
The output is:
50
50
1
Not what you expected, right?
That's because in a for loop, variables aren't updated until the loop has finished. To combat this, you can use setlocal enabledelayedexpansion, and replace the percent signs (%) with an exclamation mark (!):
#echo off
setlocal enabledelayedexpansion
set val=50
echo %val%
for /l %%i in (1,1,1,) do (
set val=%%i
echo !val!
)
echo %val%
pause>nul
The output:
50
1
1
The reason the str variable holds no value (during the for loop) is because it hasn't been set beforehand.
So, with these quick modifications, your script will work...
setlocal enabledelayedexpansion
for /f "tokens=*" %%i in (myfile) do (
set str=%%i
set str=!str: %oldstring% = %newstring%!
echo !str! >> newfile
)
By the way, this snippet is assuming that oldstring and newstring won't be set within the forloop, otherwise things will get messy.
Have fun.
having spent some time at this I got the correct way:
#echo off
setlocal enabledelayedexpansion
set oldstring=AF-07295
set /a count=1000
for %%f in (*.*) do (
set /a count=!count!+1
for /f "tokens=*" %%i in (%%f) do (
set str=%%i
call set str=%%str:!oldstring!=!count!%%
echo !str! >> %%~nf.ordnew
)
)
endlocal
setlocal ENABLEDELAYEDEXPANSION
set filein="c:\program files\test1.txt"
set fileout="c:\program files\test2.txt"
set old=#VERSION#
set new=2.0.3
for /f "tokens=* delims=¶" %%i in ( '"type %filein%"') do (
set str=%%i
set str=!str:%old%=%new%!
echo !str! >> %fileout%
)
working perfect
and isn't removing white spaces at the begining of the lines file

batch file renaming "This.is.a.FIlename.mp3" to "tiaf.mp3"

okay so I have a dir with some files. I want to do a specific file-renamingscript
i'm stuck with this part, taking only the first letter of each part of the filename:
if the filename would be
This.is.a.FIle.mp3
I would like to rename it to
tiaf.mp3
notice i want it to be all in lowercase.
The word length is variable so i cant take reference from it as a local variable !variable:~0,2!
anyone could help?
thanx!
edit: i forggot to ask. If you have an idea to make a test if the filename is of the format i mentioned. Because if the file is called. 'file.mp3' then i wouldn't want it to be renamed to 'f.mp3'
This should work, but if you want to allow also "!" exclamation marks in your filenames, it have to be a little bit extended.
#echo off
setlocal EnableDelayedExpansion
for %%f in ("C:\temp\folder\*.*") do (
call :createName "%%~f"
)
goto :eof
:: Compress a filename with more than one dot to only the first (lower) letters of each part
:: one.TWO.three.four.exe to ottf.exe
:createName <dot-filename>
setlocal
set "filename=#.%~n1"
set "ext=%~x1"
set "count=0"
set "short="
:createName.loop
for %%a in ("!filename!") do (
set "part=%%~xa"
set "filename=%%~na"
if defined part (
set /a count+=1
set "char=!part:~1,1!"
call :toLower char
set "short=!char!!short!"
) ELSE (
set "char="
)
rem echo "%%~na"-"%%~xa" "!char!" "!short!"
)
if defined part goto :createName.loop
set "short=!short!!ext!"
if !count! GTR 1 (
echo ren "%~f1" "!short!"
)
(
endlocal
goto :eof
)
:: convert a char to the lower variant or leave it unchanged if it isn't a char
:: use the %var:*n=% syntax to remove the front of a string, to get the correct char
:toLower <variable to char>
setlocal EnableDelayedExpansion
(
set "char=!%~1!"
set "helper=##aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz"
set "lower=!helper:*%char%=!"
set "lower=!lower:~0,1!"
if "!lower!"=="#" set "lower=!char!"
)
(
endlocal
set "%~1=%lower%"
goto :eof
)
Would this kind of logic work for you:
#echo off
for /f "delims=|" %%f in ('dir /b C:\temp') do call :runsub %%f
goto EOF
:runsub
for /f "tokens=1,2,3,4 delims=." %%a in ("%~n1") do set a=%%a&set b=%%b&set c=%%c&set d=%%d
if not "%a%"=="" echo %a%
if not "%b%"=="" echo %b%
if not "%c%"=="" echo %c%
if not "%d%"=="" echo %d%
:EOF
You can change the echo %a%, echo %b%, etc. to sets and get the substring from these. This also only gets the first 4 splits, you can add more if you need. Also change C:\temp to the appropriate directory.

Resources