I found this line of code on this site that echos a text file line by line:
FOR /F %%i IN (filename.txt) DO echo %%i
I am trying to echo a specific line in the text file. How would I accomplish this?
This method get the desired result in a faster way, especially if the file is large.
#echo off
set "line=100"
(for /L %%i in (1,1,%line%) do set /P "result=") < filename.txt
echo %result%
This will echo line 100.
#echo off
set "var=100"
for /f "tokens=1,* delims=:" %%a in ('findstr /n "^" "filename.txt" ^|findstr "^%var%:"') do echo %%b
Lines starting with : will not be complete.
Related
I am trying to write a batch script that reads 18th line from a .log file and outputs the same. The .log file name varies each time. abc_XXXX.log where xxxx are process IDs. Below is the code I am trying to run to achieve this.
:Test1
set "xprvar=" for /F "skip=17 delims=" %%p in (abc*.log) do (echo %%p& goto
break)
:break
pause
goto END
set var=anyCommand doesn't work. It just sets the var to the literal string.
The usage of afor /f is the right way, just the variable assignment works different:
for /F "skip=17 delims=" %%p in ('dir /b abc*.log') do ( set "xprvar=%%p"& goto break )
There is also an option using FindStr
#Echo Off
For /F "Tokens=1-2* Delims=:" %%A In ('FindStr/N "^" "abc_*.log" 2^>Nul'
) Do If %%B Equ 18 Echo %%A:%%C
Pause
The above example Echoes the <filename>:<18th line content>, but there's no reason in the appropriate situation why you couldn't change that to read:
#Echo Off
For /F "Tokens=1-2* Delims=:" %%A In ('FindStr/N "^" "abc_*.log" 2^>Nul'
) Do If %%B Equ 18 Set "xprvar=%%C"
If there is more than one matching filename in the directory, the variable would be set to the content in the last file parsed.
#ECHO Off
SETLOCAL
FOR %%f IN (abc*.log) DO (
SET "reported="
FOR /f "skip=17delims=" %%p IN (%%f) DO IF NOT DEFINED reported (
ECHO %%p
SET "reported=Y"
)
)
Assign each filename in turn to %%f.
For each filename found, clear the reported flag then read the file, skipping the first 17 lines. echo the 18th line and set the reported flag so that the remainder of the lines are not echoed.
This information below is contained in a text file and formatted as such.
/var/www/xxx/html/videos/video_folder_1
/var/www/xxx/html/videos/video_folder_2
/var/www/xxx/html/videos/video_folder_3
/var/www/xxx/html/videos/video_folder_4
/var/www/xxx/html/videos/video_folder_5
/var/www/xxx/html/videos/video_folder_6
/var/www/xxx/html/videos/video_folder_7
I also have a variable called %file_name% in the batch file already defined.
So lets say that is it is %file_name% = V001-video_folder_6.mp4
As you can see there is some more extra information, V001- and .mp4.
I would like to use the var %file_name% to search the text file and return the entire line. In this case it would return /var/www/xxx/html/videos/video_folder_6 and then put this information in a new var, let us say, %folder_path%.
I think I would use findstr however I have been playing around and not getting the best results.
The problem with the methods that use findstr is that they are slow, because they require to execute findstr.exe (a ~30KB file) each time. A simpler/faster solution is to use just internal Batch commands with the aid of an array. If the number of names to process is large, the difference in time between the two methods may be marked.
#echo off
setlocal EnableDelayedExpansion
rem Load the lines from text file into an array with the last part as index:
for /F "delims=" %%a in (test.txt) do (
set "line=%%a"
for %%b in (!line:/^= !) do set "lastPart=%%b"
set "folder[!lastPart!]=%%a"
)
set "file_name=V001-video_folder_6.mp4"
rem Get the folder from file_name:
for /F "tokens=2 delims=-." %%a in ("%file_name%") do set "folder_path=!folder[%%a]!"
echo Folder path is: %folder_path%
Let us assume the posted lines are in file Test.txt in current working directory.
#echo off
set "file_name=V001-video_folder_6.mp4"
for /F "tokens=2 delims=-." %%A in ("%file_name%") do set "folder=%%A"
for /F "delims=" %%P in ('%SystemRoot%\System32\findstr.exe "/C:%folder%" Test.txt') do (
set "folder_path=%%P"
goto NextCommand
)
:NextCommand
echo Full folder path is: %folder_path%
Open a command prompt window, enter the command for /?, hit key RETURN or ENTER and read output help to understand this little code.
The command goto inside FOR loop results in an immediate exit from loop processing output of findstr.exe after first found line containing the folder path of interest.
Perhaps better in case of searched folder is not found in text file:
#echo off
set "file_name=V01-VIDEOS for school (Miss Patrick).mp4"
for /F "tokens=2 delims=-." %%A in ("%file_name%") do set "folder=%%A"
for /F "delims=" %%P in ('%SystemRoot%\System32\findstr.exe "/C:%folder%" Test.txt') do (
set "folder_path=%%P"
goto FoundFolder
)
echo "%folder%" not found in file Test.txt.
pause
goto :EOF
:FoundFolder
echo Full folder path is: "%folder_path%"
pause
This should work:
::file_name=V001-video_folder_6.mp4
::file containing folder paths is called paths.txt
for /f "tokens=2 delims=-." %%a in ("%file_name%") do set FN=%%a
for /f %%a in ('findstr /E /L "%FN%" "paths.txt"') do set folder_path=%%a
echo %folder_path%
Which does what you want in effectively two lines.
I have a number of text files that are always the same number of lines - 42 and always the same type of information on each line. Also each line starts with a header.
What I would like is a batch script to keep line 30 of the text file remove the others and save the file.
I have tried to look find the line based on the information between two line. In this case the heading on line 30 (Job Notes) and the heading on line 31 (Job Number) and then write the information to a new file.
Line 30 begins with
Job Notes= (information specifically about the job)
Line 31 begins with
Job Number=
This is the code I used (which i found elsewhere on this site) and i am getting no output at all. Have tried other ways as well so don't really have to use this method if you can see a better one, basically i just want line 30 to be the only information in the file.
#ECHO OFF
SETLOCAL
SET "sourcedir=C\Batch"
SET "destdir=C:\Batch\Extract"
for /f "tokens=1 delims=[]" %%a in ('find /n "Job Notes"^<"%sourcedir%\7099.txt" ') do set /a start=%%a
for /f "tokens=1 delims=[]" %%a in ('find /n "Job Number"^<"%sourcedir%\7099.txt" ') do set /a end=%%a
(
for /f "tokens=1* delims=[]" %%a in ('find /n /v ""^<"%sourcedir%\00007099.txt" ') do (
IF %%a geq %start% IF %%a leq %end% ECHO(%%b
)
)>"%destdir%\newfile.txt"
GOTO :EOF
Any help would be greatly appreciated.
David
Option 1, using findstr string numeration
for %%a in (*.log) do (
for /f "tokens=1,* delims=:" %%b in (
'findstr /n "^" "%%a" ^| findstr /b "30:"'
) do (
echo(%%c>"%%a"
)
)
Option 2, using for command skip lines
setlocal disabledelayedexpansion
for %%a in (*.log) do (
set "line="
for /f "usebackq skip=29 delims=" %%b in ("%%a") do if not defined line set "line=%%b"
setlocal enabledelayedexpansion
echo(!line!>"%%a"
endlocal
)
You want you the /N flag with FINDSTR:
FINDSTR /N /R ".*" *.txt | FINDSTR /R "\<30:" > out.txt
Explanation:
FINDSTR /N /R ".*" *.txt
finds every line (".*" with the regex flag /R) in every text file (*.txt) and appends its line number to the front (/N). This is then piped to
FINDSTR /R "\<30:"
which only grabs lines starting with (that's the \< bit) 30:.
#ECHO OFF
SETLOCAL
SET "sourcedir=C\Batch"
SET "destdir=C:\Batch\Extract"
for /f "skip=29tokens=1* delims==" %%a in ('type "%sourcedir%\7099.txt" ') do ECHO(%%b >"%destdir%\newfile.txt"&goto nextstep
:nextstep
GOTO :EOF
should do the job, finding line 30 (by skipping 29) then tokenising on the separating = and having output exactly one, going to the next step in your batch.
Having said that, however - you do realise that you are setting start and end using 7099.txt and then picking the data from 00007099.txt don't you? Does 00007099.txt exist?
And c:\batch seems a mighty strange place to store data files to me. Personally, I'd put batch files there (and include c:\batch into your PATH) but it's your system...
I need to extract a line into a file based on the line number that I got in a loop For. In fact, I get the line 7 from the first FOR command, so far so good and I have to read this line into myfile.txt. The reading operation is performed in the second FOR loop; this step does not work since I get output 'result.txt' empty
for /f "tokens=1* delims=:" %%a in (lines.txt) do set line=%%a& goto breakFor "%line%"
:breakFor
echo.%line%
for /f "tokens=*" %%a in ('findstr /n .* "myfile.txt"') do if "%%a"=="%1" set line=%%i
echo.%line%>result.txt
Here's a part of myfile.txt and lines.txt
lines.txt
7:I=output7
515:I=output515
837:I=output837
851:I=output851
myfile.txt is made of lines of text (I1,I2,I3,...)
I1=some text....
I2=text...
Could you please tell me why and help to fix that?
Thanks
The Batch file below do the following:
Read the first line of the file lines.txt
Get the number that appear before a semicolon
Use this number to locate that line in myfile.txt
Show that line
.
for /f "tokens=1* delims=:" %%a in (lines.txt) do set line=%%a& goto breakFor
:breakFor
echo.%line%
for /f "tokens=1* delims=:" %%a in ('findstr /n "^" "myfile.txt" ^| findstr "^%line%:') do set line=%%b
echo.%line%>result.txt
Is this what you want? I would prefer do it this way:
for /f "tokens=1* delims=:" %%a in (lines.txt) do set /A line=%%a-1& goto breakA
:breakA
echo.%line%
for /f "skip=%line% tokens=1* delims=:" %%a in ('findstr /n "^" "myfile.txt"') do set line=%%b& goto breakB
:breakB
echo.%line%>result.txt
try this and look at the output:
#echo off &setlocal
set "line=test"
goto breakFor "%line%"
:breakFor
echo "%~1"
I am looking to find a batch or VBS solution to strip out lines in a program generated text file with the extension of .trs.
In every .trs file created there is a line that contains the word 'labour'. I need every line after the line that contains the word labour to be deleted.
The .trs files are all stored in c:\export
I have searched for this but some of the commands were well over my head. Could anyone be so kind as to offer me a cut and paste open of the whole batch file, please.
I believe this is the code you are looking for (in a batch file) to remove all of the lines above the word "labour". Let me know if modifications need to be made to the code (such as if there are more than one instance of "labour" in the file).
#echo OFF
setLocal EnableDelayedExpansion
cd C:\export
for /f "delims=" %%I in ('findstr /inc:"labour" "test.trs"') do (
set /A"line=%%I"
)
set count=0
for /f "delims=" %%A in (test.trs) do (
If !count! GEQ %line% goto ExitLoop
echo %%A >>temp.txt
set /A count+=1
echo !count!
)
:ExitLoop
type temp.txt > test.trs
del temp.txt
endlocal
OUTPUT:
test.trs (BEFORE changes)
this
is
a
labour
test
of
the
results
test.trs (AFTER changes)
this
is
a
Here is an alternate method to process every .trs file in "C:\export":
#echo off
if not exist "C:\export\*.trs" goto :EOF
if exist "C:\export\queue.tmp" del /q "C:\export\queue.tmp"
for /f "tokens=*" %%A in ('dir /b "C:\export\*.trs"') do (
for /f "tokens=1,2 delims=:" %%B in ('findstr /inc:"labour" "C:\export\%%A" ^| findstr /n .*') do if "%%B" equ "1" set LineNumber=%%C
for /f "tokens=1* delims=:" %%D in ('findstr /n .* "C:\export\%%A"') do if %%D lss %LineNumber% echo.%%E>>"C:\export\queue.tmp"
move /y "C:\export\queue.tmp" "C:\export\%%A">NUL
)
First, I do some error checking to avoid things that would break the script. Next, I pull a list of .trs files stored in C:\export, and loop through each file.
I use 'findstr /inc:"labour" "C:\export\%%A"' to get the line number where "labour" is found in the current file, then pipe it into 'findstr /n .*' to number the results in case more than one match is found.
I then use a for loop with "tokens=1,2 delims=:" to find the first result (if "%%B" equ "1") and store the line number (set LineNumber=%%C).
Next, I use 'findstr /n .* "C:\export\%%A"' to read every line of the file, "tokens=1* delims=:" to separate out the line numbers again, then copy all the data to a temp file until %LineNumber% has been reached. This method of reading the file (using findstr and numbering the lines) also ensures that no blank lines will be skipped by the for loop.
Finally, I replace the original file with the temp file, then loop through to the next file.
I tried to keep the above code as slimmed down as possible. Here is the same script with formatting, comments, visual feedback, and user-definable variables:
#echo off
::Set user-defined Variables
set FilePath=C:\export
set FileType=*.trs
set Keyword=labour
::Check for files to process and exit if none are found
if not exist "%FilePath%\%FileType%" echo Error. No files to process.&goto :EOF
::Delete temp file if one already exists
if exist "%FilePath%\queue.tmp" del /q "%FilePath%\queue.tmp"
::List all files in the above specified destination, then process them one at a time
for /f "tokens=*" %%A in ('dir /b "%FilePath%\%FileType%"') do (
::Echo the text without a line feed (so that "Done" ends up on the same line)
set /p NUL=Processing file "C:\export\%%A"... <NUL
::Search the current file for the specified keyword, and store the line number in a variable
for /f "tokens=1,2 delims=:" %%B in ('findstr /inc:"%Keyword%" "%FilePath%\%%A" ^| findstr /n .*') do (
if "%%B" equ "1" set LineNumber=%%C
)>NUL
::Output all data from the current file to a temporary file, until the line number found above has been reached
for /f "tokens=1* delims=:" %%D in ('findstr /n .* "%FilePath%\%%A"') do (
if %%D lss %LineNumber% echo.%%E>>"%FilePath%\queue.tmp"
)>NUL
::Replace the current file with the processed data from the temp file
move /y "%FilePath%\queue.tmp" "%FilePath%\%%A">NUL
echo Done.
)