Batch script to find files that contains two consecutive lines - regex

I'm trying to code a Batch script to find txt files in a folder (and recursively in subfolders) that contain these two consecutive lines (no spaces between the lines):
Code "5898"
Price "50"
I tried with this:
Findstr -m /S /C:"Code ""5898""\r\n Price ""50"" *.txt" >> output.txt
but I don't know how to manage the carriage return and the newline. If I try to find the string without using Price ""50"" it works fine while no good results if I try to look for the two lines I need.

Please do not alter this file, doing so would probably cause it not to work.
#Echo Off
SetLocal EnableDelayedExpansion
For /F %%A In ('Copy /Z "%~dpf0" Nul') Do Set "CR=%%A"
Set LF=^
Dir/B/S/A-D|Findstr/RNF:"/" /C:"Code \"5898\"!CR!*!LF!Price \"50\"">"%tmp%\$_.tmp"
>Output.txt ( For /F "UseBackTokens=1-3 Delims=:" %%A In ("%tmp%\$_.tmp") Do (
Echo("%%A:%%B"))
Del "%tmp%\$_.tmp"
To output only the filename, (odd when the search is recursive):
#Echo Off
SetLocal EnableDelayedExpansion
For /F %%A In ('Copy /Z "%~dpf0" Nul') Do Set "CR=%%A"
Set LF=^
Dir/B/S/A-D|Findstr/RNF:"/" /C:"Code \"5898\"!CR!*!LF!Price \"50\"">"%tmp%\$_.tmp"
>Output.txt ( For /F "UseBackTokens=1-3 Delims=:" %%A In ("%tmp%\$_.tmp") Do (
Echo("%%~nxB"))
Del "%tmp%\$_.tmp"
You could technically change the Tokens to 1-2 now but I'll leave it as is so it is easier to re-implement the line number check again, If %%C==1 before the echo on the second last line if ever necessary.

Related

How to subtract string and non-null value entries from txt file?

I have a script that extracts lines such as :
THIS_IS_A_LINE:=
THIS_IS_A_LINE2:=
and outputs all of the same kind into another .txt file as:
THIS_IS_A_LINE
THIS_IS_A_LINE2
The script is the following:
set "file=%cd%/Config.mak"
set /a i=0
set "regexp=.*:=$"
setlocal enableDelayedExpansion
IF EXIST Source_List.txt del /F Source_List.txt
for /f "usebackq delims=" %%a in ("%file%") do (
set /a i+=1
call set Feature[!i!]=%%a
)
cd .. && cd ..
rem call echo.!Feature[%i%]!
for /L %%N in (1,1,%i%) do (
echo(!Feature[%%N]!|findstr /R /C:"%regexp%" >nul && (
call echo FOUND
call set /a j+=1
call set Feature_Disabled[%j%]=!Feature[%%N]:~0,-2!
call echo.!Feature_Disabled[%j%]!>>Source_List.txt
) || (
call echo NOT FOUND
)
)
endlocal
I also have another script that extracts lines such as:
THIS_IS_ANOTHER_LINE:=true
THIS_IS_ANOTHER_LINE2:=true
...
and outputs all of the same kind into another .txt file as:
THIS_IS_ANOTHER_LINE
THIS_IS_ANOTHER_LINE2
...
The script is the following:
set "file=%cd%/Config.mak"
set /a i=0
set "regexp=.*:=true$"
setlocal enableDelayedExpansion
IF EXIST Source_List2.txt del /F Source_List2.txt
for /f "usebackq delims=" %%a in ("%file%") do (
set /a i+=1
call set Feature[!i!]=%%a
)
cd .. && cd ..
rem call echo.!Feature[%i%]!
for /L %%N in (1,1,%i%) do (
echo(!Feature[%%N]!|findstr /R /C:"%regexp%" >nul && (
call echo FOUND
call set /a j+=1
call set Feature_Disabled[%j%]=!Feature[%%N]:~0,-6!
call echo.!Feature_Disabled[%j%]!>>Source_List2.txt
) || (
call echo NOT FOUND
)
)
endlocal
Nevertheless, there is a third kind of lines which contain numerical numbers (also some hexadecimal values), such as:
THIS_IS_AN_UNPROCESSED_LINE:=0xA303
THIS_IS_AN_UNPROCESSED_LINE2:=1943
THIS_IS_AN_UNPROCESSED_LINE3:=HELLO_DOOD_CAN_YOU_PARSE_ME?
So I need the way to extract as well those kind of lines into another .txt file such as:
THIS_IS_AN_UNPROCESSED_LINE:=0xA303
THIS_IS_AN_UNPROCESSED_LINE2:=1943
THIS_IS_AN_UNPROCESSED_LINE3:=HELLO_DOOD_CAN_YOU_PARSE_ME?
So basically extract lines which are not of the kind:
THIS_IS_AN_UNPROCESSED_LINE:=
or
THIS_IS_AN_UNPROCESSED_LINE:=true
but keeping both the sides of the line entry.
I know there must be some trick with the regular expression but I just can't find it out.
You have made your code much more complicated than it needs to be. There is no need to create an array of every line in the file.
If there are no other : or = before the first :=, then you can use FINDSTR to print out all lines that contain a string, followed by :=. FOR /F can capture and parse each matching line into the parts before and after :=, and then IF statements can classify the three different types of lines.
I use n> to open all three output files outside the main code block for improved performance, and then I use the &n> syntax to direct each output to the appropriate, already opened file. I use high numbered file handles to avoid problems described at Why doesn't my stderr redirection end after command finishes? And how do I fix it?.
#echo off
setlocal
set "file=Config.mak"
set /a "empty=7, true=8, unprocessed=9"
%empty%>empty.txt %true%>true.txt %unprocessed%>unprocessed.txt (
for /f "delims=:= tokens=1*" %%A in ('findstr /r "^[^:=][^:=]*:=" "%file%"') do (
if "%%B" equ "" (
>&%empty% (echo %%A)
) else if "%%B" equ "true" (
>&%true% (echo %%A)
) else (
>&%unprocessed% (echo %%A:=%%B)
)
)
)
The above will ignore lines that contain : or = before :=, and it will not work properly if the first character after := is : or =. I'm assuming that should not be a problem.
It should be relatively easy to write a very efficient solution using PowerShell, VBScript, or JScript that eliminates the limitations.
You could also use JREPL.BAT - a powerful and efficient regular expression text processing command line utility. JREPL.BAT is pure script (hybrid batch/JScrpt) that runs natively on any Windows machine from XP onward, no 3rd party exe required. And JREPL is much faster than any pure batch solution, especially if the files are large.
Here is one JREPL solution
#echo off
setlocal
set repl=^
$txt=false;^
if ($2=='') stdout.WriteLine($1);^
else if ($2=='true') stderr.WriteLine($1);^
else $txt=$0;
call jrepl "^(.+):=(.*)$" "%repl%" /jmatchq^
/f Config.mak /o unprocessed.txt >empty.txt 2>true.txt
If all you have to do is classify the lines into three different files, without worrying about stripping off the :=true and := parts for the empty and true lines, then there is a very simple pure batch solution using nothing but FINDSTR.
#echo off
set "file=Config.mak"
findstr /r ".:=$" "%file%" >empty.txt
findstr /r ".:=true$" "%file%" >true.txt
findstr /r ".:=" "%file%" | findstr /r /v ":=$ :=true$" >unprocessed.txt

Batch Splitting a line of text into multiple lines, delimited by quotation space quotation

Thanks in Advance.
Using a DOS batch file, I am trying to read a text file that contains several full paths with quotes, separated by a space and write a new file containing one path per line.
For example, I want to turn this file:
"C:\path\filename.doc" "C:\path\filename.doc" "C:\path\filename.doc" "C:\path\filename.doc"
into this:
"C:\path\filename.doc"
"C:\path\filename.doc"
"C:\path\filename.doc"
"C:\path\filename.doc"
I have had some success using the wonderful repl.bat (by dbenham).
type "files.txt" | repl " " "\r\n" x l >"newfile.txt"
But when there are spaces in the filenames or path it breaks a new line in the middle of the path and wrecks it.
Ive tried passing as the search variable into repl using the escape character ^, i.e. repl "^" ^"" and other ways with no joy.
At the end of the day, I simply need to move all the files into another directory, and so was going to then pass the resulting text file to another bulk delete batch file for processing, but perhaps there is a better way im missing ?
This has a limitation in the length of the line, of around 8 KB.
Less than that and it will move the files to your new folder.
#echo off
for /f "usebackq delims=" %%a in ("c:\folder\file.txt") do (
for %%b in (%%a) do move "%%~b" "d:\existing\new\folder"
)
The code below should work to move all files in except the ones in the list.
It adds a hidden attribute to the files in the list, moves all the other files, then removes the hidden attributes again.
#echo off
for /f "usebackq delims=" %%a in ("c:\folder\file.txt") do (
for %%b in (%%a) do attrib +h "%%~b"
)
cd /d "c:\folder"
move *.* "d:\already\existing folder"
for /f "usebackq delims=" %%a in ("c:\folder\file.txt") do (
for %%b in (%%a) do attrib -h "%%~b"
)
Test code for Windows 2012 as mentioned in the comments
#echo off
(echo "c:\widget1\test 1.txt" "2:\widget2\test 2.doc")>"file.txt"
for /f "usebackq delims=" %%a in ("file.txt") do (
for %%b in (%%a) do echo move "%%~b" "d:\existing\new\folder"
)
pause
You could use the following batch file split.bat and call it redirecting the content of your text file into it and redirecting the output into another file like split.bat < files.txt > newfiles.txt:
#echo off
set /P INFILE=
call :SPLIT %INFILE%
exit /B
:SPLIT
shift
if "%~0"=="" exit /B
echo "%~0"
goto :SPLIT
If you do not provide an input file (< files.txt) the scripts prompts you for a space-separated list.
If no output file is given (> newfiles.txt), the created new-line-separated list is shown on screen.
Notice that this does not verify whether your input file fulfills the described formatting.
This method is limited to a list length of 1021 bytes (characters), everything after will be truncated!
Assuming you can guarantee that each file path is enclosed within double quotes, then you just need to tweak your REPL.BAT command a bit:
type "files.txt" | repl "(\q.*?\q) *" "$1\r\n" x >"newfile.txt"
But REPL.BAT has been superseded by JREPL.BAT - it has even more functionality, and a slightly different syntax.
A JREPL solution can be as simple as:
jrepl "\q.*?\q" $0 /x /jmatch /f file.txt /o newfile.txt
If you want, you can overwrite the original file with the result by specifying - as the output file.
jrepl "\q.*?\q" $0 /x /jmatch /f file.txt /o -
If each line in the original file is <8k, then the following pure batch script should work, and it is pretty simple:
#echo off
>newfile.txt (
for /f "delims=" %%A in (files.txt) do for %%B in (%%A) do echo %%B
)

Trim extra pipes off end of text file in Windows

So basically I have a process that outputs a text file that is pipe delimited, looks something like this:
|abc123|1*|004|**gobbligook|001|%|2014-01-01|||||||||||||
This is just an example, and I'm not sure if the answer involves regular expressions. If it does i will put the actual line. Anyways
ISSUE
So for this example the import process that accepts this file is looking for 8 pipes, but there are 20, if it sees any more pipes after the 8 it's looking for the import process fails.
Question
Is there a process that I can use in a Windows environment to trim the trailing pipes off the end of this for the entire file?
UPDATE
Magoo supplied me with a great answer that I am working but I keep getting this error: Delimiter was unexpected at this time
Here is code:
#ECHO OFF
SETLOCAL
SET "sourcedir=C:\Users\Desktop\Pipe Delimiter Project"
SET "destdir=C:\Users\Desktop\Pipe Delimiter Project"
(
FOR /f "tokens=1-7delims=|" %%a IN ('TYPE "%sourcedir%\test.txt"') DO (
ECHO(^|%%a^|%%b^|%%c^|%%d^|%%e^|%%f^|%%g^|
)
)>%destdir%\newfile.txt
Anyone know what's wrong? I also just put in the line from the question |abc123|..| pasted in the file like 6 times...thanks!
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=."
SET "destdir=U:\destdir"
(
FOR /f "delims=" %%a IN ('TYPE "%sourcedir%\q22863616.txt"') DO (
SET "line=%%a"
ECHO(!line:~0,-12!
)
)>%destdir%\newfile.txt
GOTO :EOF
I used a file named q22863616.txt containing your data for my testing.
Produces newfile.txt
Assuming that the final 12 fields are all empty, for lack of information otherwise.
Another form, given additional information
#ECHO OFF
SETLOCAL
SET "sourcedir=."
SET "destdir=U:\destdir"
(
FOR /f "tokens=1-7delims=|" %%a IN ('TYPE "%sourcedir%\q22863616.txt"') DO (
ECHO(^|%%a^|%%b^|%%c^|%%d^|%%e^|%%f^|%%g^|
)
)>%destdir%\newfile.txt
OK - third time's a charm.
#ECHO OFF
SETLOCAL enabledelayedexpansion
SET "sourcedir=."
SET "destdir=U:\destdir"
:: remove variables starting $
FOR /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="
(
FOR /f "delims=" %%a IN ('TYPE "%sourcedir%\q22863616.txt"') DO (
SET "$0=%%a"
SET "$1=%%a"
FOR /l %%c IN (1,1,8) DO SET "$1=!$1:*|=!"
SET "$2=%%a"
SET "$3="
SET /a tot=0
FOR /f "delims=:" %%e IN ('set $^|findstr /o /r "$"') DO SET /a tot=%%e - !tot! - 5
CALL :show !tot!
CALL ECHO %%$2:~0,-!tot!%%
)
)>%destdir%\newfile.txt
GOTO :EOF
:show
CALL SET "$3=%%$2:~0,-%1%%"
FOR /f "tokens=1*delims==" %%y IN ('set $3') DO ECHO(%%z
GOTO :eof
This seems immune to % in the data, but chokes on ! or &. You pays your money, you takes your choice...
This should eat trailing pipes but leave 8 of them
#echo off
type "file.txt"| repl "(.*?\|{8})\|*$" "$1" >"newfile.txt"
This uses a helper batch file called repl.bat - download from: https://www.dropbox.com/s/qidqwztmetbvklt/repl.bat
Place repl.bat in the same folder as the batch file or in a folder that is on the path.

Extract number from string in batch file

From a batch file I want to extract the number 653456 from the following string:
C:\Users\testing\AppData\Local\Test\abc123\643456\VSALBT81_COM
The number will change, however it will always be just digits.
My current theory is to search for something that fits \alldigits\, then replace the two \s with white space, but I can’t quite get it.
Assuming the number is always the parent folder (the folder before the end):
#echo off
set "str=C:\Users\testing\AppData\Local\Test\abc123\643456\VSALBT81_COM"
for %%F in ("%str%\..") do set "number=%%~nxF"
EDIT - Code sample adapted to correct errors shown in comments
set d=C:\Users\testing\AppData\Local\Test\abc123\643456\VSALBT81_COM
for %%f in ("%d:\=" "%") do for /f %%n in ('echo %%f^|findstr /b /e /r "\"[0-9]*\""') do (
echo %%~n
)
Just precede the path with a quote, split the path, replacing each backslash with a quote a space and a quote and append a quote (so we have a list of elements to iterate), and for each part check if it is formed only by numbers
#echo off
setlocal EnableDelayedExpansion
set "string=C:\Users\testing\AppData\Local\Test\abc123\643456\VSALBT81_COM"
for /L %%d in (0,1,9) do set "string=!string:\%%d=\ %%d!"
for /F "tokens=2" %%a in ("%string%") do for /F "delims=\" %%b in ("%%a") do echo Number: [%%b]
This uses a helper batch file called repl.bat from - https://www.dropbox.com/s/qidqwztmetbvklt/repl.bat
#echo off
set "string=C:\Users\testing\AppData\Local\Test\abc123\643456\VSALBT81_COM"
echo "%string%"|repl ".*\\([0-9]*)\\.*" "$1"
Here is how I striped numbers from a string in batch (not a file path, should be generically working for a "string")
#ECHO OFF
::set mystring=Microsoft Office 64-bit Components 2013
set mystring=Microsoft 365 Apps for enterprise - en-us
echo mystring = %mystring%
for /f "tokens=1-20 delims=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!##$&*()-= " %%a in ("%mystring%") do (
IF %%a == 64 (
set ONum=%%b
GoTo varset
)
IF %%a == 32 (
set ONum=%%b
GoTo varset
)
set ONum=%%a
)
:varset
echo numfromalphanumstr = %numfromalphanumstr%
pause
https://www.dostips.com/forum/viewtopic.php?t=3499
https://superuser.com/questions/1065531/filter-only-numbers-0-9-in-output-in-classic-windows-cmd
Extract number from string in batch file
How to extract number from string in BATCH

Batch File List

i have made a batch script creating a loterry game and with users.
The userscore is saved in in DLL datas saved in C:\RTD.
I know there are already some answers about this but i got a different meaning.
Is it possible to list the filenames somewhere without extension but also with the content !
I'd like to make a score list so it could look like this :
User1 : 25 Points
User2 : 65 Points
Banaman : 81 Points
The best would be if the thing is saved in a .txt or .dat file ...
You can try this but if you want to sort it by score later on then it would be wise to use fixed fields and entries padded with spaces. Or just pad the score with leading spaces and put the score as the first thing on each line, in the file.
#echo off
del "hiscore.dat" 2>nul
pushd "C:\RTD"
for %%a in (*.dll) do (
for /f "delims=" %%b in ('type "%%a" ') do (
>>"hiscore.dat" echo %%~na - %%b points
)
)
type "hiscore.dat"
popd
This should pad the score with leading spaces which can be sorted with the sort command.
#echo off
setlocal enabledelayedexpansion
del "hiscore.dat" 2>nul
pushd "C:\RTD"
for %%a in (*.dll) do (
for /f "delims=" %%b in ('type "%%a" ') do (
set var= %%b
set var=!var:~-10!
>>"hiscore.dat" echo !var! points by %%~na
)
)
type "hiscore.dat" |sort
popd
try this:
for %%i in (c:\rtd\*.dll) do echo %%~ni>> saved.txt