cmd Text Search & Print - sorting

I've been tasked with extracting some data from a text file and I was wondering if anyone knows a quick cmd method to my problem.
The file I need to search is quite large, consisting of repetitive records.
What I'm looking to do is search for one line of text, say:
'searchForThisLineOfText'
Then, when it's found, go to the next line down from that text, and write that line to a file.
So the contents of the file looks somting like this:
searchForThisLineOfText
563473
someOtherLine
34583933
anotherline
2342
searchForThisLineOfText
3424
someOtherLine
34583933
anotherline
2342
From that, I would like to write the numbers 563473 and 3424 to a file.
Anybody have any ideas on how to do this?
Thanks in advance.

#ECHO OFF
SETLOCAL
SET "found="
(
FOR /f "delims=" %%a IN (q25871330.txt) DO (
IF DEFINED found ECHO %%a
IF "%%a"=="searchForThisLineOfText" (SET "found=Y") ELSE (SET "found=")
)
)>newfile.txt
GOTO :EOF
I used a file named q25871330.txt containing your data for my testing.
Produces newfile.txt

This assumes that the blank lines are not actually in the text file.
#echo off
type "file.txt" | findrepl "searchForThisLineOfText" /o:1:1 >"newfile.txt"
pause
This uses a helper batch file called findrepl.bat (by aacini) - download from: https://www.dropbox.com/s/rfdldmcb6vwi9xc/findrepl.bat
Place findrepl.bat in the same folder as the batch file or on the path.

This will generate a temporary file with the number of the lines that need to be retrieved and then retrieves the required lines
#echo off
setlocal enableextensions enabledelayedexpansion
rem We will need a temporary file
set "tempFile=%temp%\%~nx0.%random%.tmp"
rem Get the number of the lines that we need to retrieve
(
for /f "delims=:" %%a in ('
findstr /n /l /c:"searchText" "data.txt"
') do ( set /a "n=%%a+1" & echo(!n!:)
)>"%tempFile%"
rem Retrieve the indicated lines to the output file
(
for /f "tokens=1,* delims=:" %%a in ('
findstr /n /r /c:"^" "data.txt"
^| findstr /b /l /g:"%tempFile%"
') do echo(%%b
)>"outputFile.txt"
rem Remove the temporary file
del "%tempFile%" > nul 2>nul

Related

Reading line by line from one file and write to another file using batch script

In below code i am tring to fetch the line no of string "AXX0000XXXA" from file data.txt,then fetching line by line and printing target.txt file,in between if the line reach the find line no i am adding one more line from file temp.txt.The code is working fine with the less nos of records(tested with 150 lines-File Size 100 kb),but when i am processing with 50K records(File Size 25MB) it is taking more then 25 minutes to process.could you please help me how i will process same in less time.
#echo off
setlocal enabledelayedexpansion
for /f "delims=:" %%a in ('findstr /n "AXX0000XXXA" "C:\Users\23456\Desktop\data.txt"') do (set find_line=%%a)
set /a counter=0
for /f "usebackq delims=" %%b in (`"findstr /n ^^ C:\Users\23456\Desktop\data.txt"`) do (
set curr_line=%%b
set /a counter=!counter!+1
if !counter! equ !find_line! (
type temp.txt >> target.txt
)
call :print_line curr_line
)
endlocal
:print_line
setlocal enabledelayedexpansion
set line=!%1!
set line=!line:*:=!
echo !line!>>target.txt
endlocal
Your code uses three Batch file constructs that are inherently slow: call command, >> append redirection and setlocal/endlocal, and these constructs are executed once per each file line! It would be faster to include the subroutine into the original code to avoid the call and setlocal commands, and an echo !line!>>target.txt command imply open the file, search for the end, append the data and close the file, so it is faster to use this construct: (for ...) > target.txt that just open the file once. An example of a code with such changes is in Compo's answer.
This is another method to solve this problem that may run faster when the search line is placed towards the beginning of the file:
#echo off
setlocal enabledelayedexpansion
for /f "delims=:" %%a in ('findstr /n "AXX0000XXXA" "C:\Users\23456\Desktop\data.txt"') do (set /A find_line=%%a-1)
call :processFile < "C:\Users\23456\Desktop\data.txt" > target.txt
goto :EOF
:processFile
rem Duplicate the first %find_line%-1 lines
for /L %%i in (1,1,%find_line%) do (
set /P "line="
echo !line!
)
rem Insert the additional line
type temp.txt
rem Copy the rest of lines
findstr ^^
exit /B
This should create target.txt with content matching data.txt except for an inserted line taken from tmp.txt immediately above the line matching the search string, AXX0000XXXA.
#Echo Off
Set "fSrc=C:\Users\23456\Desktop\data.txt"
Set "iSrc=temp.txt"
Set "sStr=AXX0000XXXA"
Set "fDst=target.txt"
Set "iStr="
Set/P "iStr="<"%iSrc%" 2>Nul
If Not Defined iStr Exit/B
Set "nStr="
For /F "Delims=:" %%A In ('FindStr/N "%sStr%" "%fSrc%" 2^>Nul') Do Set "nStr=%%A"
If Not Defined nStr Exit/B
( For /F "Tokens=1*Delims=:" %%A In ('FindStr/N "^" "%fSrc%"') Do (
If "%%A"=="%nStr%" Echo %iStr%
Echo %%B))>"%fDst%"
I have made it easy for you to change your variable data, you only need to alter lines 3-6.
I have assumed that this was your intention, your question was not clear, please accept my apologies if I have assumed incorrectly.

Batch file for /f isnt reading files

Lots of issues With batch coding... Things just don't seem to work the way i expect them to.
So I am Using a batch file to Extract Text data from .as Files. I managed to get that working However It creates a bunch of Junk/empty txt files that don't have any useful content extracted from them. So I made another batch file that gets called from main.bat and is supposed to Clean the empty files, however the variables are incorrect even though the for loop in main.bat is almost identical.
Full Copies of the batch files main.bat and Clean.bat
The Issue Is the Bit of Code below (From Clean.bat line 33) #note the following code had most of its counters and echos removed
#echo off
cls
setlocal enabledelayedexpansion
for /r %%Z in (*.txt) do (
SET /a count=0
for /F "eol= tokens=1 delims=," %%A in ("%%Z") do (
if /i %%A==LN set /a count+=1
)
if !count! EQU 0 (
rem del "%%Z")
)
pause
In this Code %%A and %%Z Are both Equal to The Full File Path of the file that should be getting read from. When %%A should be token 1 of The txt file in question. Because of this count always = 0 so it always deletes the file (thats why del is commented out).
Here's an Example of the file its supposed to read from
LN,296,textE("海沿いに立つ高級フィットネスリゾート施設。");
LN,299,textE("夏休み、俺たち兄妹は、陸上の強化合宿という「名目」のもと、\nこの施設を訪れていた。");
LN,302,textE("莉 央\nすごい、すごい!!おしゃれなところだねー!");
Basically Its supposed to check each line and if LN doesnt Exist as the first token to any line it deletes the file. (Because that means the file is empty except for a Line count of the Original .as file)
This may work for you given the things you have said:
I interpreted your point to mean that if the file doesn't contain LN as the first token on any line, then it is to be deleted.
#echo off
for /r %%Z in (*.txt) do (
SET "count="
for /F "usebackq delims=," %%A in ("%%Z") do (
if /i "%%A"=="LN" set count=1
)
if not defined count echo del "%%Z"
)
pause
This is another way to do the same thing:
#echo off
for /r %%Z in (*.txt) do (
findstr "^LN," "%%Z" >nul || echo del "%%Z"
)
pause

Want to split a text file into one file per line

I have a text file that is generated daily that has between 20 and 50 lines, each ending with a set delimiter, currently ~ but that can be changed to anything. I want to take this text file and split it into 20 to 50 different files, with one line per file. Ideally I'd like to do this from a windows batch file, or at least a program that I can script to run daily. Appreciate any help you can provide, thanks!
Sample Input File:
GS*SH*CSMZ9*20131209*0908*000000001*X*004010|ST*856*0001|BSN*00*000000001~
GS*SH*CSMZ9*20131209*0912*003400004*X*004010|SG*834*0001|TSN*00*000000004~
GS*SH*CSMZ5*20131209*1001*000040007*X*004010|ST*855*0001|BSN*00*000000007~
GS*SH*CSMZ9*20131209*1019*000000010*X*004010|SG*856*0001|BGN*00*000000010~
for /f "tokens=1*delims=:" %%a in ('findstr /n "^" "file.txt"') do for /f "delims=~" %%c in ("%%~b") do >"text%%a.txt" echo(%%c
I propose python here. Much more readable that any shell script.
f=open("filename")
lines = f.read().split('~')
for (n, line) in enumerate(lines):
open( "newname{}".format(n), "w" ).write(line)
This should create files called 00000001.txt and increment the number for each line.
If any line contains ! then it needs an extra modification.
#echo off
setlocal enabledelayedexpansion
set c=0
for /f "delims=" %%a in (file.txt) do (
set /a c+=1
set name=0000000!c!
set name=!name:~-8!.txt
>!name! echo %%a
)
#ECHO OFF
SETLOCAL
SET "destdir=c:\destdir"
FOR /f "tokens=1*delims=:" %%a IN ('findstr /n "." q21239387.txt') DO (
>"%destdir%\filename%%a.txt" ECHO(%%b
)
GOTO :EOF
where q21239387.txt is the name of the file I used as input for testing.
Files filename1.txt..filename99.txt created in the destination directory (99 is # lines in the file)
Note - will not correctly output source lines that begin with : if that is a problem.

How to batch rename files in a directory from a list of names in a text file

I'd like to use Power Shell or a batch file to rename several files in a folder based on a list in a text file. Essentially I want to append the file names with the author's last names (which I have stored in a separate text file).
E.g. Currently I have:
C:\myfiles
9-ART-2013.pdf
4-EGO-2013.pdf
2-ART-2013.pdf
My text file (in same order as files):
C:\myfiles
_Smith
_Jenkins
_McMaster
I want the files to be renamed as follows:
9-ART-2013_Smith.pdf
4-EGO-2013_Jenkins.pdf
2-ART-2013_McMaster.pdf
I've seen similar problems where people want to recursively rename files but they are always using a generic common appending element like adding an underscore or pre-pending with folder name, etc.
e.g. https://serverfault.com/questions/6268/easy-way-to-rename-all-files-in-a-directory-in-windows
In PowerShell it would be:
$names = Get-Content c\myfiles
Get-ChildItem C:\somedir\*.pdf | Sort -desc |
Foreach {$i=0} {Rename-Item $_ ($_.basename + $names[$i++] + $_.extension) -WhatIf}
If it looks like it will copy correctly, remove the -WhatIf.
Any of the above are likely workable solutions with just a little tweaking but the simplest thing to do was to simply create one text file with each row containing "the current filename"... a TAB... then "the filename I wanted".
9-ART-2013.pdf 9-ART-2013_Smith.pdf
4-EGO-2013.pdf 4-EGO-2013_Jenkins.pdf
2-ART-2013.pdf 2-ART-2013_McMaster.pdf
Then save the file as rename_list.txt and create a batch file with the following code.
for /F "tokens=1,2" %%a in (rename_list.txt) do ren "%%a" "%%b"
pause
You can delete the pause line once you get it tweaked and running correctly. Just copy the rename_list.txt and batch files to the folder with the files you want to rename and run the batch file. If you have a large folder with many files names you can get them in a text file by running a batch file with the following line.
dir /D > filename_scrapper_output.txt
It will create a text file filename_scrapper_output.txt that you can use to start your rename_list.txt file for above.
Another way to achieve the same thing:
#echo off
setlocal EnableDelayedExpansion
rem Load the list of authors:
set i=0
for /F %%a in (myfiles.txt) do (
set /A i+=1
set "author[!i!]=%%a"
)
rem Do the rename:
set i=0
for /F %%a in ('dir /b *.pdf') do (
set /A i+=1
for %%i in (!i!) do ren "%%a" "%%~Na!author[%%i]!%%~Xa"
)
EDIT: New method added
If the list of names file have the "OLD-Name NEW-Name" structure, then the code is much simpler:
for /F "tokens=1,2" %%a in (myfiles.txt) do ren "%%a" "%%b"
Note that the names must be separated by a space.
#ECHO OFF &SETLOCAL ENABLEDELAYEDEXPANSION
<Text.txt (
for /f "tokens=1*delims=_" %%a in ('dir /b /a-d /o-d *-*-*.pdf') do if "%%b"=="" (
set "xand="
set /p "xand="
echo ren "%%~a" "%%~na!xand!%%~xa"
))
Taking Endoro's and simplifying:
#ECHO OFF &SETLOCAL ENABLEDELAYEDEXPANSION
<texts.txt (
for /f "tokens=* delims=* " %%a in ('dir /b /a-d /o-d *-*-*.pdf') do (
set "xand="
set /p "xand="
ren "%%~a" "%%~na!xand!%%~xa"
))

Insert Into Multiple Files in Windows shell script

Basically I'm trying to write a batch file to insert some code into multiple files. Here are the details of what I'm tring to accomplish:
1. The input string comes from a file test.txt.
2. The string needs to be inserted as the second line of destination files.
3. Destination files are all the .xml files under the same direction as the batch file.
I suppose I should use a FOR loop to go through all .xml files. Something like
for /f %%i in ('dir /b *.xml') do ()
I've read though some tutorials and posts but can't find a way to add anything to files in a loop. Using Echo or TYPE doesn't seems to work for each file in a loop. How do I modify files in a loop?
Also to insert to a certain number of line some post say the file needs to be put into a variable. But my files are pretty large, which I don't want to put into variables. Is there another way to insert into a certain line in a file?
#ECHO OFF
SETLOCAL
FOR /f "delims=" %%i IN ('dir /b *.xml') DO (
SET line2=Y
(
FOR /f "usebackqdelims=" %%x IN ("%%i") DO (
ECHO(%%x
IF DEFINED line2 TYPE Line2.txt
SET "line2="
)
)>"%%~ni.lmx"
)
GOTO :EOF
This should work for you - but it will delete empty lines.
#echo off
set /P string=< test.txt
for %%a in (*.xml) do (
(for /F "usebackq tokens=1* delims=:" %%b in ('findstr /N "^" "%%a"') do (
if %%b equ 2 echo %string%
set "line=%%c"
setlocal EnableDelayedExpansion
echo(!line!
endlocal
)) > "%%a.new"
)
New files have .xml.new extension; you may add a couple lines to delete original .xml files and rename .xml.new ones to .xml.

Resources