I have multiple files such as qulogscan_141201.txt (year month day)
am trying to create a batch which will pick that file and find "notloaded" inside it, what I have done so far is this:
Echo NOTLOADED
Echo\
set yy=%date:~-2%
set mm=%date:~-7,2%
set dd=%date:~-10,2%
setlocal EnableDelayedExpansion
rem Assemble the list of line numbers
set numbers=
set "folder=J:\Console\Output_Del\sscmex\qulogscan_%yy%%mm%%dd%.txt"
for /F "delims=:" %%a in ('findstr /I /N /C:"NOTLOADED" "%folder%"') do (
set /A after=%%a+3
set "numbers=!numbers!!after!: "
)
rem Search for the lines
(for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "%folder%" ^| findstr /B "%numbers%"') do echo %%b)
how can I do to make it select the file qulogscan_.txt ignoring the datastamps without renaming it ?
Related
Thanks in advance for any help given.
After searching through all relative threads and google search I'm stumped on finding a solution to output a variable name for merging two PDF's.
So I have 100's of PDF's I need to combine (two at a time) in a folder c:/test
The files are set out like below
Company Name Invoice No 123456
Company Name Invoice No 123456 details
Now I have managed to move two files at a time to a different folder and merge them but can't seem to get the desrired output name I'm after which is to put a week ending date in front (or at the end, not fussed) of the first merged filename. Below is the code I have thus far which works but the output file name is blank but gets created.
Very new to batch scripting and would appreciate any help :)
#echo off
setlocal enableextensions enabledelayedexpansion
set pdftk=C:\Program Files (x86)\PDFtk Server\bin\pdftk.exe
set Source=C:\test
set Target=C:\test\test2
set num=2
set filenumber=1
for /F "tokens=1,2 delims=:" %%f in ('dir /b /a-d "%source%\*.pdf" ^| findstr /n "^" ') do (
if %%f leq %num% (
copy "%source%\%%g" "%target%" /y > nul
) else goto endCopy
)
:endCopy
endlocal
for /F "tokens=1,2 delims=:" %%f in ('dir /b /a-d "%target%\*.pdf" ^| findstr /n "^" ') do (
if %%f leq %filenumber% ( set file=%%~nA
)
)
pdftk *.pdf cat output we_19_9_2017_%file%.pdf
In endCopy you are trying to get the name of A whereas you are iterating with f. Use set file=%%~nf to set the name of file or set file=%%~ng for second file.
And move endlocal at the end to expand !file! at the end of script like this (note the !):
:endCopy
set "cmd=dir /b /a-d "%target%\*.pdf" ^| findstr /n "^""
for /F "tokens=1,2 delims=:" %%f in ('%cmd%') do if %%f leq %filenumber% set file=%%~nf
pdftk *.pdf cat output we_19_9_2017_!file!.pdf
endlocal
Read more about DelayedExpansion at: https://ss64.com/nt/delayedexpansion.html
The last command doesn't use the target folder for the input files and thus looks for the input files in the current folder, so either include the path or first change to the target path.
Also you set a path-variable for pdftk but don't use it.
If this path isn't included in the %path% it can't be find.
Try this (untested)
#echo off
setlocal enableextensions enabledelayedexpansion
set "pdftk=C:\Program Files (x86)\PDFtk Server\bin\pdftk.exe"
set "Source=C:\test"
set "Target=C:\test\test2"
set num=2
set filenumber=1
for /F "tokens=1,2 delims=:" %%f in (
'dir /b /a-d "%source%\*.pdf" ^| findstr /n "^" '
) do if %%f leq %num% (
copy "%source%\%%g" "%target%" /y > nul
) else goto endCopy
:endCopy
endlocal
for /F "tokens=1,2 delims=:" %%f in (
'dir /b /a-d "%target%\*.pdf" ^|findstr /n "^" '
) do if %%f leq %filenumber% set file=%%~nf
PushD "%Target%"
"%pdftk%" *.pdf cat output we_19_9_2017_%file%.pdf
PopD
I have a series of text files each named the same in sub-folders of a certain directory
ac.txt files have the following structure :
---
some text
---
[lights]
---
some text
---
[GetEngineData]
---
some text
---
I want to get all those lines in between strings [lights] and [GetEngineData] (including those start [lights] and end [GetEngineData] lines) in one single output file called lights.txt with a blank space in between those coming from each text file.
I coded the following batch yet it is of no avail so far :
#ECHO OFF
for /r %%a in ('find /n "[lights]"^<(ac.txt) ') do set /a start=%%a
for /r %%a in ('find /n "[GeneralEngineData]"^<(ac.txt) ') do set /a end=%%a
(
for /r %%a in ('find /n /v ""^<(ac.txt) ') do (
IF %%a geq %start% IF %%f leq %end% ECHO(%%b
)
)>lights.txt
Here's a way to do it. Might not be the most efficient but it seems to do the job just fine. The code loops through all subfolders and picks up all .TXT files. It then parses each line of each file, marking the beginning/end of each block using the [lights] and [GeneralEngineData] tokens and then outputs everything to res.txt in the same folder where the batch file is stored.
#ECHO OFF
Setlocal EnableDelayedExpansion
if exist res.txt del res.txt
set inblock=0
for /r . %%a in (*.txt) do (
set fname=%%a
for /f "tokens=1* delims=]" %%b in ('type "!fname!" ^| find /n /v ""') do (
if /i *%%c*==*[lights]* set inblock=1
if !inblock!==1 (
if *%%c*==** (echo.) else (echo %%c)
if /i *%%c*==*[GetEngineData]* set inblock=0
)
)
echo.
) >> res.txt
set fname=
set inblock=
type res.txt
I want to store the result of a command in a variable in a for loop in a batch script. I want to loop through a series of .sql files, count how many lines each file consists of and sum up the line counts.
Here is my attempt so far:
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /a count=0
set /a t=0
for /f %%a in ('dir /b *.sql') do (
#echo %%a <- THIS PRINTS THE FILE NAME
#set t=findstr /r /n "^" %%a | find /C ":" <- THIS IS INCORRECT
echo %t% <- I WANT TO PRINT THE LINE COUNT FOR THE FILE
#set /a count+=%t% <- INCREASE THE COUNTER
)
echo %count% <- PRINT TOTAL LINE COUNT
When I run
findstr /r /n "^" *.sql | find /C ":"
in a command window it works, and I know I could use that for the end objective, but this question is about the variable assignment.
Where is my mistake? The variable t is assigned the value 0 all the time.
UPDATE: (Still not working)
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /a count=0
set /a t=0
for /f %%a in ('dir /b *.sql') do (
#echo %%a
for /L %%b in ('findstr /r /n "^" %%a ^| find /C ":"') do (
set /a count+=%%b
)
)
echo !count!
For anyone interested reading this later, here is the final (working version):
#ECHO off
SETLOCAL ENABLEDELAYEDEXPANSION
SET /a count=0
SET /a t=0
for /f %%a in ('dir /b *.sql') do (
#echo %%a
for /f %%b in ('findstr /r /n "^" %%a ^| find /C ":"') do (
set t=%%b
)
ECHO !t!
#SET /a count+=!t!
)
ECHO "Total:" !count!
#set t=findstr /r /n "^" %%a | find /C ":" <- THIS IS INCORRECT
doesn't work. It sets the variable t to the string findstr /r /n "^" %%a and filters the Output of the set command (which Outputs nothing) with | find /C ":", which Counts exactly Zero colons in nothing.
The best way of doing it, is:
for /f %%x in ('findstr /r /n "^" %%a ^| find /C ":"') do set t=%%x
Edit I was so focussed on repairing your code, that I didn't really realize, that you just want to count all lines of all *.SQL files. That's quite easy. No need for delayed expansion:
set count=0
for /f %%a in ('type *.sql 2^>nul ^| find /n /v ""') do set /a count+=1
echo %count%
2>nul prevents type to print the file names to the screen.
Edit2
my solution with 203 files, 47763 lines in total needs about 24 seconds. Aschipfl's edit2 solution about seven milliseconds. Impressive... find /c must have a really efficient method to count the lines.
My slightly changed code to use this capability:
set count=0
for /f %%a in ('type *.sql 2^>nul ^| find /c /n /v ""') do set /a count+=%%a
echo %count%
which also needs about 7ms. No big surprise, as it's basically the same code as Aschipfl's - just formatted differently.
There is no need to use findstr /N /R "^" to precede each line with line number and : and count the number of lines containing : afterwards.
To count the number of lines a text file contains, you only need to redirect it into find /C /V "", like this:
< "\path\to\file.txt" find /C /V ""
To use this within your for loop, you could do this:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set /A COUNT=0
set /A T=0
for /F "eol=| delims=" %%A in ('dir /B "*.sql"') do (
setlocal DisableDelayedExpansion
echo(%%~A
for /F %%B in ('^< "%%~A" find /C /V ""') do (
endlocal
set /A T=%%B
)
echo(!T!
set /A COUNT+=T
)
echo Total: %COUNT%
endlocal
exit /B
The toggling of delayed expansion is done to avoid trouble with exclamation marks ! in any of the *.sql file names, which would be ignored otherwise and the error message The system cannot find the file specified. would appear. Delayed expansion is only required because of the (debug) line echo(!T!; if you remove that, you can disable delayed expansion for the entire script.
Edit #1:
Here is a compacted variant of the above script, without any temporary variable T and with delayed expansion disabled:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set /A COUNT=0
for /F "eol=| delims=" %%A in ('dir /B "*.sql"') do (
for /F %%B in ('^< "%%~A" find /C /V ""') do (
echo(%%~A: %%B
set /A COUNT+=%%B
)
)
echo TOTAL: %COUNT%
endlocal
exit /B
And here is a script that uses a single for /F loop to retrieve the number of lines, which lets find search for the *.sql files like find /C /V "" "*.sql", then takes its output that looks like ---------- file.sql: 5 for instance, splits off the count after : and sums up all of them. This approach needs delayed expansion again:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set /A COUNT=0
for /F "eol=| delims=" %%A in ('find /C /V "" "*.sql"') do (
set "LINE=%%~A"
echo(%%~A
setlocal EnableDelayedExpansion
set /A T=!LINE:*: =!
for /F "delims=" %%B in ("!T!") do (endlocal & set /A COUNT+=%%B)
)
echo TOTAL: %COUNT%
endlocal
exit /B
Yes, there is a second for /F loop nested as well, but this is required for transferring the value of T over the endlocal barrier.
Edit #2:
Here is probably the best solution for determining the total number of lines over multiple files. This lets type output every line of all the *.sql files, which are then counted by find. Therefore the for /F loop iterates once only, so the overall performance of this script is quite great:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set /A COUNT=0
for /F "delims=" %%A in ('
2^>nul type "*.sql" ^| find /C /V ""
') do (
set /A COUNT+=%%A
)
echo TOTAL: %COUNT%
endlocal
exit /B
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.
I have a folder where files are dumped with timestamps...
filename_ver20130405121320.csv
I wish to create a batch script that makes sure 5 files have been created with todays date.
im guessing i will need to use a for loop with a date limit of today.
FOR /r %foldername% %%g IN (*.csv) DO (
echo %%~nxg
)
using a forfiles statement lists the files, is it possible to use a counter and +=1 every time it displays a filename?
forfiles /S /P %foldername% /m *.csv /d 0
the logic is
if number of files in a foldername is less than 5 where file created is today
echo error! missing files
any help would be much appreciated
date returned on machine as Mon 22/07/2013
use this to set date
:: set date
FOR /F "TOKENS=1* DELIMS= " %%A IN ('DATE/T') DO SET CDATE=%%B
FOR /F "TOKENS=1,2 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET dd=%%B
FOR /F "TOKENS=1,2 DELIMS=/ eol=/" %%A IN ('echo %CDATE%') DO SET mm=%%B
FOR /F "TOKENS=2,3 DELIMS=/ " %%A IN ('echo %CDATE%') DO SET yyyy=%%B
SET setDate=%dd%/%mm%/%yyyy%
#ECHO OFF
SETLOCAL enabledelayedexpansion
SET yyyy=2013
SET mm=07
SET dd=22
SET count=0
FOR /f %%g IN ('dir /b /a-d *%yyyy%%mm%%dd%????.csv') DO (
SET filename=%%~ng
SET filename=!filename:~-12,-4!
if "!filename!"=="%yyyy%%mm%%dd%" SET /a count+=1
)
ECHO %count%
GOTO :EOF
I've simply set yyyy,mm,dd to constants, obviously - just poke your date-decoder in as appropriate.
Note that you could prefix the filemask with a directoryname if required - and enclose the entire filemask in "rabbit's ears" if there are spaces or other confounding characters in the resultant mask.
Important: the filemask is merely a primary filter. The dir would list a file named filename_ver2013040512132.csv for instance (1 digit missing...) so the gymnastics with the processing would still be required.
I'm also assuming relatively sane filenames. Likely ! in a filename would cause conniptions.
I came up with this and it seems to work so far
for /f "tokens=2" %%I in ("%date%") do set today=%%I
for /f "tokens=5" %%G in ('dir %foldername% /a-d ^| find "%today%"') do (
set /a fileCounter += 1
echo %%G
)
echo %fileCounter%
This may work (untested): edited to check only the date in yyyymmdd format
#echo off
for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set dt=%%a
set datestamp=%dt:~0,8%
for /f %%a in ('dir "*ver%datestamp%*.csv" /b /a-d^|find /c /v "" ') do (
if %%a LSS 5 echo files are missing
)