Batch print line until string found - batch-file

I have a batch script that generates a file with the following structure (example)
123|etc|etc
345|etc|etc
678|etc|etc
I want my script to print out what it finds in each line, until it finds a |, so in this example i would want it to print:
123
345
678, and so on.
I've tried findstr /V with the | but it completely ignores the line (as the command states it will)
Any idea how could i turn this around?

#echo off
for /f "usebackq tokens=1 delims=|" %%a in ("test.txt") do (
echo %%a )
pause
This is looping through a file (test.txt) in the same directory as the batch script. I tell it to only use 1 token with a pipe delimiter then we just print out %%a which has the value of your first column of data.

Related

Batch Script to extract lines Between two given words

I need to extract texts between two given words from a file.
The File format is as below :
some lines
<name>text1</name>
some lines
some lines
<name>text2</name>
some lines
<name>text3</name>
some more lines
I need to extract all the occurrences of texts that occur between each of the name tags
<name> extract this text here </name>
Expected Output for above file :
text1
text2
text3
Thank you.
This should work for the sample data provided:
for /f "tokens=2 delims=<>" %A in ('type test.txt ^| findstr "<name>"') do #echo %A
If using this inside of a batch script, be sure to change %A to %%A. Basically, this will run through lines containing <name>, and split the line by < and > characters using delims=<>, giving you name, text in between, /name. The tokens=2 sets %A to only the second string.
Keep in mind this won't work if you have anything on the line before <name>. That would probably complicate things a lot more in batch, and I would then suggest using some parsing library in another language for that.
Also, this will not work if the text you wanted to extract contains < or >.
The following script extracts the text in between the desired tags of the file(s) provided as command line argument(s):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Resolve command line arguments:
for %%F in (%*) do (
rem // Read a single line of text following certain criteria:
for /F "delims=" %%L in ('
findstr /R "^[^<>]*<name>[^<>][^<>]*</name>[^<>]*$" "%%~F"
') do (
set "LINE=%%L"
rem /* Extract the desired string portion;
rem the preceding `_` is inserted for the first token
rem never to appear empty to the `for /F` loop: */
setlocal EnableDelayedExpansion
for /F "tokens=3 delims=<>" %%K in ("_!LINE!") do (
endlocal
rem // Return found string portion:
echo(%%K
)
)
)
endlocal
exit /B
This works only if there is exactly one tag <name>, followed by some text not containing < and > on its own, followed by exactly one tag </name>; this string must be on a single line and may be preceded or followed by some texts not containing < and > on their own.
Suppose the input file is input.txt.
This should work :
grep '<name>.*</name>' input.txt | sed -r 's/<name>(.*)<\/name>/\1/'
grep finds the lines
sed deletes the name tags

How can i get all of the 2nd line only of my stats.txt file?

i currently have this command for a batch file
for /F "skip=1 tokens=1 delims=\n" %i in (stats.txt) do echo %i
with the contents of stats.txt being
Title = Subaru's Great Rehab Strategy
URL = http://dynasty-scans.com/chapters/subarus_great_rehab_strategy
Tags = Subaru x Tsukasa[|]Yuri[|]
No. of Pages = 3
^ NOTE: the final line is actually blank
the idea of the line of code is to return the 2nd line with URL. the end goal would be that i would run this line in some sort of loop going though a series of ~12000+ stats.txt files and collecting all the URL lines into a single file
but when i run the command i get this
as you can see it has skipped the first line but it's cutting off where the n in dynasty and outputting the last 3 lines.
now if i remove delims=\n i get the same 3 lines but i don't get the first word before the space which seems to indicate that the value of delims is what splits a line into "tokens" which then i just grab the first one (and space must be the default)
when i go into notepad++, open the Find and Replace Dialog, turn Search Mode to extended and look for "\r\n" i get taken to the end of each line which is why i chose delims to be \n assuming this would then make the entire line one token
So my question is How can i get all of the 2nd line only of my stats.txt file?
The for /f loop already treats the carriage return and / or line feed as an end-of-line. No need to specify it as a delimiter. With delims=\n you're actually saying that all literal backslashes and letter n's should be treated as token delimiters. If you want the whole line, what you want is "skip=1 delims=".
Just out of habit, when reading the contents of a file with a for /f loop, I find it useful to enable usebackq just in case the filename / path contains a space or ampersand. That allows you to quote the filename to protect against such potential treachery.
#echo off
setlocal
for /F "usebackq skip=1 delims=" %%I in ("stats.txt") do if not defined URL set "URL=%%~I"
echo %URL%
Put into context, to use this to read many files named stats.txt and output the URLs into a single collection, enclose the whole thing in another for loop and enable delayed expansion.
#echo off
setlocal
>URLs.txt (
for /R %%N in ("*stats.txt") do (
for /F "usebackq skip=1 delims=" %%I in ("%%~fN") do (
if not defined URL set "URL=%%~I"
)
setlocal enabledelayedexpansion
echo(!URL!
endlocal
set "URL="
)
)
echo Done. The results are in URLs.txt.
If you want to strip the "URL = " from the beginning of each line and keep only the address, you could try changing your for /F parameters to "usebackq skip=1 tokens=3" if all the files follow the same format of URLSpace=Spacehttp://etc.. If you can't depend on that, or if any of the URLs might contain unencoded spaces, you could also change echo(!URL! to echo(!URL:*http=http!
You don't need to use a FOR /F loop, you can also read it with a SET /P
setlocal EnableDelayedExpansion
< stats.txt (
set /p line1=
set /p URL_Line=
)
echo(!URL_Line!
Try this from the command line:
(for /F "tokens=1* delims=:" %i in ('findstr "URL" stats*.txt') do echo %j) > output.txt
the idea ... is to return the 2nd line with URL
If you want to insert this line in a Batch file, just double the percent signs.
Try this from the prompt:
(for /f "tokens=1*delims=]" %a in ('find /v /n "" *.csv^|findstr /l /b "[2]"') do #echo %b)>u:\r1.txt
Where - I used *.csv for testing (substitute your own filemask) and I used u:\r1.txt for the result - substitute as seems fit (but don't output to a file tat fits your selected filemask !)
It works by prefixing each line in each file with a bracketed number [n] (find - /n=and number /v lines that do not match "" - an empty string); then selecting those lines that /l - literally /b at the beginning of the line match "[2]".
The result is all of the second-lines of the files, preceded by the literal "[2]". All we need to do then is tokenise the result, first token up to delimiter "]" will be "[2" assgned to %%a and remainder-of line (token *) will be assigned to %%b
Have you tried
for /F "skip=1 tokens=1 delims=\n" %i in (stats.txt) do echo %i && goto :eof
I haven't tested it as I don't have access to a Windows machine at the moment, but that should exit the for-loop after the first iteration, which is what you want.

How to remove a line from the output with a .bat file?

I have a utility (myexefile.exe) which outputs a list of information like this:
Line1=[Information in line1]
Line2=[Information in line2]
Line3=[Information in line3]
Line4=[Information in line4]
, etc.
I use a .bat file to write this information to a text file like this:
set myexefile="c:\myexefile.exe"
set outputfile="c:\outputfile.txt"
%myexefile% >> %outputfile%
However, I would like to write all of the lines except for the line containing "Line3=".
So I want the output to the outputfile.txt to be:
Line1=[Information in line1]
Line2=[Information in line2]
Line4=[Information in line4]
, etc.
I could probably create the file as it is and then use an existing sample which shows how to remove a line from a text file, but I would rather skip the line in the first place, rather than writing it to a text file and then removing it.
Can someone help me with this?
%myexefile% | find /v "Product ID">> %outputfile%
should filter out any line containing Product ID
setLocal enableDelayedExpansion
set outputfile="c:\outputfile.txt"
for /f "delims=" %%a in ('c:\myexefile.exe') do (
set out=%%a
if "!out:~0,4!" NEQ "Line3" echo %%a>>%outputfile%
)
or alternatively -
set outputfile="c:\outputfile.txt"
for /f "delims=" %%a in ('c:\myexefile.exe') do for /f %%b "delims=:" in ("%%a") do if "%%b" NEQ "Line3" echo %%a>>%outputfile%

batch command "skip=2 Delims="

I had the below code in one of the make files.
#for /F "skip=2 Delims=" %%i in ('<somefile>') do echo Code-%%i
Could anybody tell what is this batch command would do?
As it is written
#for /F "skip=2 Delims=" %%i in ('<somefile>') do echo Code-%%i
this means: Execute (not read file, execute, there are simple quotes) <somefile>, take its output to standard stream, skip the two first lines, and for each line with content, assign this line contents to %%i, then, also for each line, output to console the text Code- followed by the content of the readed line (that is inside %%i).
The # at the start of the line means not to echo to console the for command.
The delims with no value assigned indicates that lines should not be considered as a concatenation of fields with a delimiter between them, that have to be splitted.

Windows Command batch script to add filename to end of each row in a merged text file

I a new to windows command line scripts.
I have a batch file which i use to merge multiple text files into one. However i want to be able to also add the name of the text file the row comes from to the end of each row in the merged file.
This is the script i am currently working with:
#ECHO OFF
ECHO Creating %1...
FOR /F "usebackq tokens=1" %%G IN (`DIR /B "C:\My Documents\Data\*.txt"`) DO
(
ECHO Adding %%G
ECHO. >> Output.txt
TYPE %%G >> Output.txt
)
Now i know that to get the filename into the output file i need to use:
ECHO %%G >> Output.txt
However i'm not sure how i would add this to the current script so it adds the filename to each row and I have had no luck with finding any examples.
There is a simple two liner that works from the command line if you are willing to prefix each line with the file name instead of putting the file name at the end. This solution is extremely fast.
cd "C:\My Documents\Data"
findstr "^" *.txt >output.log
Each line will have the format of filename:line content
It is important that your output file use a different extension than the files you are merging. Otherwise you run the risk of the command processing its own output!
The other option is to make sure the output goes to a different folder, perhaps the parent folder:
cd "C:\My Documents\Data"
findstr "^" *.txt >..\output.txt
Or, if you are willing to include the full path to each file in your output, then make sure current directory is not the same as your source, and use
findstr "^" "C:\My Documents\Data\*.txt" >output.txt
The only drawback to the above solution is that problems can arise if the last line of a text file does not end with a newline character. This will cause the first line of the next file to be appended to the last line of the prior file. Something like: FILENAME1:last line without newlineFILENAME2:first line of next file
A simple script can append a newline to files that are missing the newline on the last line. Then the files can be safely merged with the filename prefix on each line:
#echo off
if "%~1" equ ":FindFiles" goto :FindFiles
cd "C:\My Documents\Data"
:: Append newline to text files that are missing newline on last line
for /f "eol=: delims=" %%F in ('"%~f0" :FindFiles') do echo(>>"%%F"
:: Merge the text files and prefix each line with file name
findstr "^" *.txt >output.log
exit /b
:FindFiles
setlocal enableDelayedExpansion
:: Define LF to contain a newline character
set lf=^
:: The above 2 blank lines are critical - do not remove
:: List files that are missing newline on last line
findstr /vm "!lf!" *.txt
You'll need to add each line in the file individually:
#ECHO OFF
ECHO Creating %1...
SET "sourcedir=c:\sourcedir"
FOR /F "delims=" %%G IN ('DIR /B /a-d "%sourcedir%\*.txt"') DO (
ECHO Adding %%G
ECHO. >> Output.txt
for /f "usebackq tokens=*" %%a in ("%sourcedir%\%%~G") do (
Echo %%a - %%G >> Output.txt
)
)
Note in the second last line, the file name and the line is seperated by a -, you can replace this with whatever (don't forget to check for escaping characters) or can get rid of this if you want.
I'm sure that will work, but if it doesn't, tell me the Error message and I can fix it for you.
Mona
---- [edit:pw]
Close - major problem was the ( on the FOR ... %%G line was on the line following the DO - must be on the same line as the DO.
Added /a-d to the DIR to prevent subdirectory names matching
changed "usebackq tokens=1" to use conventional quotes and allow spaces in filenames
assigned target directory name to sourcedir variable and included %sourcedir% in both FOR statements to allow execution from anywhere, otherwise the filenames found in C:\My Doc.... would be searched-for in the current directory for replication into the output.
OP needs to change value assigned to sourcedir to C:\My
Documents\Data

Resources