I really don't understand why the first batch script is working and second not. I need to use the second batch script as I need to add more conditional inside the loop.
The script counts the number of lines in .txt file and make a separate variable for each of the lines
this version is working
#echo off
setlocal EnableDelayedExpansion
for /f "tokens=2 delims='" %%B in ('type "output-mp3.txt"') do set /a "nlines+=1+0" && <con: set "_line!nlines!=%%~nB"
echo line 1 !_line1!
echo line 2 !_line2!
echo total number of lines !nlines! and name of the song !_line2!
pause
I need the add more things on the for loop so I need do (...) but is not working ..
#echo off
setlocal EnableDelayedExpansion
for /f "tokens=2 delims='" %%B in ('type "output-mp3.txt"') do (
set /a "nlines+=1+0" && <con: set "_line!nlines!=%%~nB"
echo line 1 !_line1!
echo line 2 !_line2!
echo total number of lines !nlines! and name of the song !_line2!
pause
)
output-mp3.txt contain
file '...\intro\Canal-1\Videos-10.mp3'
file 'F...Canal-1\Videos-10\0HDW0N3Q.mp3'
#echo off
setlocal EnableDelayedExpansion
for /f "tokens=2 delims='" %%B in ('type "output-mp3.txt"') do (
set /a "nlines+=1+0"
<con: set "_line!nlines!=%%~nB"
)
set _line
works for me - regardless of the number of lines in the file.
Related
Ok. this is a self updating batch file. I just simplified the problem from a bigger file.
this is a windows batch file(.bat) that upon execution should open itself and update first line
SET variableName=D:\Data
setlocal enableextensions enabledelayedexpansion
set /A i=0
for /f "tokens=*" %%f in ('type "%0"^&cd.^>"%0"') do (
set /A i=!i!+1
if !i! EQU 1 (
echo SET variableName=D:\Data2>>%0
) else (
echo %%f>>%0
)
)
endlocal
so let explain the situation.
i have !i! variable in lines 5 and 6. after executing this file, the variable in each line will replace by line number. it obviously because of echo %%f>>%0 that could not ignore and escape variable.
and my question is how to solve this problem?
another less problem is that the above code ignores spaces at beginning of line (indents) and generates a flat file.
the result of executing this file is:
SET variableName=D:\Data2
setlocal enableextensions enabledelayedexpansion
set /A i=0
for /f "tokens=*" %%f in ('type "%0"^&cd.^>"%0"') do (
set /A i=5+1
if 6 EQU 1 (
echo SET variableName=D:\Data2>>%0
) else (
echo %%f>>%0
)
)
endlocal
Stopping expansion of the variable when executing the file is as simple as turning delayed expansion off prior to the line that updates the file, and pairing it with an endlocal.
Retaining the space / tab formatting is achieved by including delims= in the For loop options.
Set variableName=D:\Data
Setlocal enableextensions enabledelayedexpansion
Set /A i=0
For /f "tokens=* delims=" %%f in ('type "%0"^&cd.^>"%0"') do (
Set /A i+=1
If !i! EQU 1 (
Echo SET variableName=D:\Data2>>%0
) Else (
Setlocal DisableDelayedExpansion
Echo(%%f>>%0
Endlocal
)
)
Endlocal
set "variableName=D:\Data"
setlocal enableextensions enabledelayedexpansion
rem !test! exclaimations, %test% percentages
for /f "skip=1 delims=" %%A in ('
type "%~f0" ^&
^> "%~f0" echo set "variableName=D:\Data2"
') do (
setlocal disabledelayedexpansion
>> "%~f0" echo %%A
endlocal
)
endlocal
You can avoid counting as skip=1 can be used to skip the first line. Use delims= to avoid delimiting the line. tokens=* ignores delimiters at start of the line and get the remainder of the line so that can be omitted for this task.
The new first line is now in the for loop command instead of erasing the file to empty. If you echo more lines, then increase the skip number.
Also may need to use setlocal disabledelayedexpansion so exclamation marks are retained.
Modifying the same file that is being read can a risk, though I assume you understand the risk.
I'm writing a Batch script that should use a .cfg to get certain information.
With "#" I can comment out in my cfg, that works fine. But now I also want to safe %%b from every loop in a different variable. How do I do that?
SETLOCAL EnableDelayedExpansion
SETLOCAL enableextensions
FOR /f "tokens=1,2 delims==" %%a in (.\test_2.44.cfg) DO (
set x=%%a
IF "!x:~0,1!"=="#" (
echo skipped
) else (
echo %%b
)
)
The .cfg
#
# test
#
NAME_LOGDATEI=.\test2.44.log
NAME_CSV=.\test_2.44.csv
#START_DIR=c:\windows
START_DIR=%ProgramFiles%
I want .\test2.44.log, .\test_2.44.csv and %ProgramFiles% each in a different variable. Now it just gives me the result of the last loop.
not tested:
SETLOCAL EnableDelayedExpansion
SETLOCAL enableextensions
set /a counter=1
FOR /f "eol=# tokens=1* delims==" %%a in (.\test_2.44.cfg) DO (
set "res[!counter!]=%%b"
set /a counter=counter+1
rem --OR--
set %%a=%%b
)
echo %START_DIR% -- %NAME_LOGDATEI%
echo %res[1]% -- %res[2]%
to skip the lines starting with # you can use eol=# in for /f options.
to save all the lines you can use pseudo array or to use the %%a token as variable name.
lets say that i have test.txt with this lines
1
2
3
i need batch file to rewrite this file as
3
2
1
in new txt file
i tried this to copy last line
for /f "delims=" %%A in (ttt.txt) do set last=%%A
echo %last%>>ttt_lastline.txt
and this to delete last line
#echo off & setlocal EnableDelayedExpansion
set row=
for /F "delims=" %%j in (File.txt) do (
if defined row echo.!row!>> File.new
set row=%%j
)
but wasn't helpful
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "destdir=U:\destdir"
SET "filename1=100lines.txt"
SET "outfile=%destdir%\outfile.txt"
SET /a count=0
FOR /f "delims=" %%a IN (%filename1%) DO (
SET /a count+=1
SET "line[!count!]=%%a"
)
(
FOR /L %%a IN (%count%,-1,1) DO ECHO(!line[%%a]!
)>"%outfile%"
GOTO :EOF
You would need to change the setting of destdir to suit your circumstances.
I used a file named 100lines.txt containing some dummy data for my testing.
Produces the file defined as %outfile%
Using delayedexpansion, read each line into line[?] using !count!, then simply echo each line loaded in reverse order.
This is a Vbscript solution.
Create a file named reverse.vbs and use this as the code.
Dim Stack: Set Stack = CreateObject("System.Collections.Stack")
Do While Not WScript.StdIn.AtEndofStream
Stack.Push WScript.StdIn.ReadLine
Loop
WScript.StdOut.WriteLine Join(Stack.ToArray, vbCrLf)
Now to reverse your file execute this from a cmd prompt or a batch file.
type input.txt |cscript //nologo Reverse.vbs>>output.txt
#echo off
setlocal enabledelayedexpansion
for /f %%a in (forward.txt) do
(
set reversed=%%a !reversed!
)
for %%i in (!reversed!) do echo.%%i >> reversed.txt
goto :eof
This is my first posting so if the format is not as it supposed to be please excuse me for this. (Suggestions for
improvement are welcome.)
I am trying to create a batchfile that will read last lines from logfiles and copy them to a new file.
Until now I have found here a way to read the last line.
Code would be something like:
for /f %%i in ('find /v /c "" ^< someFile.txt') do set /a lines=%%i
set /a startLine=%lines% - 1
more /e +%startLine% someFile.txt > lastLines.txt
The above code works for one file at a time. What I need is to read the last line from all files in a known list and add this line to a new .csv file.
I have been using the following code for getting the 4th entry in the logfiles but it returns every line of every logfile:
for /f %%x in (%list%) do for /f "delims=.txt, tokens=4" %%i in (%%x.txt) do echo %%x, %%i >> output.csv
What I would need is a sort of combination of both but I don't know how to combine them and make the complete last line be copied to the .csv file.
===
#Magoo:
Thanx for your reaction.
In every logfile can be 1 to >100 lines with comma separated information. Something like:
"LOGON,6-1-2015,12:43:39,USERNAME,HOSTNAME,,,,192.168.209.242,00:21:5A:2E:64:5E"
The last code with the 4th entry was used to get a list of all accounts that had logged in to the computers. This code gave me a very large list of all logon/logoff events on all computerlogs I checked in %list%.
In %list$ I had all the names of logfiles I wanted to be checked. This returned all lines.
For a new batchfile I need only the last logon/logoff entry and I want the whole last line.
So I have a .txt file with the hostnames of all computers I need to examine.
This .txt file will be read line by line via the variable %list%.
From every logfile I need only the last line copied to an output file.
===
I just tried the solution offered by JosefZ. Unfortunately this does not work for me yet. No lastlines are copied to the resultfile. In the code I removed the extra entry for possible lastlines for there are no empty lines in the logs, I also added an entry for the hostname I want to be available in the result. JosefZ had the filename there:
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
type nul>output.csv
set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
set "host=%%~x"
for /F "tokens=*" %%G in ('type "%%~x"') do set "lastline=%%G"
call :lline
)
:endlocal
#ENDLOCAL
goto :eof
:lline
set "filename=.\logs\%filename:&=^&%.txt"
echo %host%,%lastline%>>output.csv
goto :eof
The resultfile shows only the hostnames. I'll puzzle some more with this but all tips are welcome!
===
Got it!!!
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
type nul>output.csv
set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
set filename= :: *empty previous filename*
set lastline= :: *empty previous lastline*
set "host=%%~x"
set "filename=.\logs\%host%.txt" :: *creating the filename from path+hostname+extention*
for /F "tokens=*" %%G in ('type "%filename%"') do set "lastline=%%G"
call :lline
)
:endlocal
#ENDLOCAL
goto :eof
:lline
echo %host%,%lastline%>>output.csv
goto :eof
Your approach with line numbering could fail if a file has more trailing empty lines. Fortunately for /F loop ignores (does not iterate) empty lines; let's put to use this feature: in the script used next practices:
disabledelayedexpansion to allow ! in file names
set "list=_listing.txt" where the _listing.txt contains list of file names (full path and extension .txt including), one file name on one line: got by dir /b /s *.txt>_listing.txt
type nul>files\output.csv to empty the output file (optional)
set "lastline=!!!file empty!!!" to initialize variable %lastline%; could be set "lastline=" as well
call :lline to process variables %filename% and %lastline%
set "filename=%filename:&=^&%" to allow & in file names
The script is as follows:
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
type nul>files\output.csv
set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
set "filename=%%~x"
set "lastline=!!!file empty!!!"
rem the whole line
for /F "tokens=*" %%G in ('type "%%~x"') do set "lastline=%%G"
rem the fourth token only
rem for /F "tokens=4" %%G in ('type "%%~x"') do set "lastline=%%G"
call :lline
)
:endlocal
#ENDLOCAL
goto :eof
:lline
set "filename=%filename:&=^&%"
echo %filename% %lastline%
rem >>files\output.csv
goto :eof
Sample _listing.txt file:
d:\bat\files\1exclam!ation.txt
d:\bat\files\2exc!lam!ation.txt
d:\bat\files\11per%cent.txt
d:\bat\files\12per%cent%.txt
d:\bat\files\17per%Gcent.txt
d:\bat\files\18per%%Gcent.txt
d:\bat\files\21ampers&nd.txt
d:\bat\files\22ampers&&nd.txt
Output:
d:\bat>lastlines
d:\bat\files\1exclam!ation.txt 0 15.01.2015 1:52:28.48 -15072 20465
d:\bat\files\2exc!lam!ation.txt 6 15.01.2015 1:52:28.50 3250 16741
d:\bat\files\11per%cent.txt -8 15.01.2015 1:52:28.50 -3692 27910
d:\bat\files\12per%cent%.txt !!!file empty!!!
d:\bat\files\17per%Gcent.txt 0 15.01.2015 1:52:28.56 14508 12374
d:\bat\files\18per%%Gcent.txt 1 15.01.2015 1:52:28.56 30540 26959
d:\bat\files\21ampers&nd.txt 15.01.2015 1:22:50.18
d:\bat\files\22ampers&&nd.txt 15.01.2015 1:22:50.18
Honestly, all that ballast is for (possibly) trailing empty lines in files and for (possibly) ! and & in file names only; all could be done with
for /f %%x in (%list%) do for /f "skip=%startLine% tokens=4" %%i in (%%x) do echo %%x, %%i >> output.csv
You should use a simple FOR to iterate a list of values, not FOR /F.
Something like the following should work:
#echo off
setlocal enableDelayedExpansion
>>output.csv (
for %%F in (
"file1.log"
"file2.log"
"file3.log"
etc.
) do (
for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
more +!skip! %%F
)
)
The quotes around the file names are there in case you get a name with spaces.
You could use your LIST variable if it looks something like
set LIST="file1.log" "file2.log" "file3.log" etc.
#echo off
setlocal enableDelayedExpansion
set LIST="file1.log" "file2.log" "file3.log" etc.
>>output.csv (
for %%F in (%LIST%) do (
for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
more +!skip! %%F
)
)
If any of your file names contain the ! character, then you must toggle delayed expansion ON and OFF within your loop. Otherwise the delayed expansion will corrupt the names when %%F is expanded.
#echo off
setlocal disableDelayedExpansion
set LIST="file1.log" "file2.log" "file3.log" etc.
>>output.csv (
for %%F in (%LIST%) do (
for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
setlocal enableDelayedExpansion
more +!skip! %%F
endlocal
)
)
Need help creating a batch that displays a certain amount of text (e.g 5 lines of text) from a txt file but only below a specific key word e.g 'Home' and finally removing any duplicate text
So ,
Search for specific string e.g 'Home' any text below ‘home’ display not all just 5 lines worth and finally remove any duplicate sentence’s
I've tried modifying the following command .
#echo OFF
:: Get the number of lines in the file
set LINES=0
for /f "delims==" %%I in (data.txt) do (
set /a LINES=LINES+1
)
:: Print the last 10 lines (suggestion to use more courtsey of dmityugov)
set /a LINES=LINES-10
more +%LINES% < data.txt
Displaying lines from text file in a batch file
Read every 5th line using Batch Script
I don't know if its possible to remove duplicates
Update
Yes that right duplicate lines within the block of 5 following the keyword
However Don't worry about removing duplicates my main concern is just trying to show text below a certain string e.g Home
I have the below command but doesn't show all information below the text just one line ideally I would like to adjust the amount displayed e.g 5 lines worth of data
setlocal EnableDelayedExpansion
rem Assemble the list of line numbers
set numbers=
set "folder=C:\test\world.txt"
for /F "delims=:" %%a in ('findstr /I /N /C:"home" "%folder%"') do (
set /A before=%%a-0, after=%%a+3
set "numbers=!numbers!!before!: !after!: "
)
rem Search for the lines
(for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "%folder%" ^| findstr /B "%numbers%"') do echo. %%b)
batch script to print previous and next lines of search string in a text file
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:: remove variables starting $
For %%b IN ($) DO FOR /F "delims==" %%a In ('set %%b 2^>Nul') DO SET "%%a="
SET /a before=0
SET /a after=5
SET "target=home"
SET /a count=0
SET "file=q24813694.txt"
FOR /f "delims=:" %%a IN ('findstr /i /n /L /c:"%target%" "%file%"'
) DO SET /a $!count!=%%a-%before%&SET /a count+=1
FOR /f "tokens=1*delims=:" %%a IN ('findstr /n /r "." "%file%"') DO (
SET "printed="
FOR /f "tokens=1,2delims==" %%m IN ('set $ 2^>nul') DO IF NOT DEFINED printed IF %%a geq %%n (
SET /a count=%%n+%before%+%after%
IF %%a geq !count! (SET "%%m=") ELSE (SET "printed=Y"&ECHO %%b)
)
)
GOTO :EOF
This routine should do the trick. You'd need to set file to suit yourself, of course; and to set the target.
If you want to set the number of lines before to print, and those after (which includes the target line) then those should work, too.