Example below - 5 files will be located in the same folder.
Sales-fid1000-f100.dat
Revenue-fid1000-f100.dat
Sales-fid2000-f200.dat
Revenue-fid2000-f200.dat
Income-fid2000-f200.dat
I need to read the filename and get the number after "fid", in this case 1000 and 2000 and count the number of files associated with each "fid".
So for fid1000, there are 2 files and for fid2000, there are 3 files.
I need to write the output into a .txt file as below with first field being the fid number and second field being the count.
1000|2
2000|3
How can I generate output text file with fid and count using a Windows batch file?
#echo off
setlocal EnableDelayedExpansion
rem Process all file names
for /F "tokens=2 delims=-" %%a in ('dir /B /A-D *.dat') do (
rem Get FID from second dash-delimited token; format: "xxx-fid####-xxx.dat"
set "fid=%%a"
rem Accumulate it to the corresponding element of "count" array
set /A "count[!fid:~3!]+=1"
)
rem Create the output
(for /F "tokens=2,3 delims=[]=" %%a in ('set count[') do echo %%a^|%%b) > output.txt
For further details on array management in Batch files, see: Arrays, linked lists and other data structures in cmd.exe (batch) script
#ECHO OFF
SETLOCAL
:: remove variables starting $
FOR /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "outfile=%destdir%\outfile.txt"
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*-fid*" '
) DO (
SET "filename=%%a"
CALL :process
)
(
FOR /F "tokens=1,2delims=$=" %%a In ('set $ 2^>Nul') DO ECHO(%%a^|%%b
)>"%outfile%"
GOTO :EOF
:process
SET "filename=%filename:*-fid=%"
FOR /f "delims=-" %%q IN ("%filename%") DO SET /a $%%q+=1
GOTO :eof
You would need to change the settings of sourcedir and destdir to suit your circumstances.
Produces the file defined as %outfile%
After clearing all the $ variables (for safety's sake), perform a directory listing without directorynames and in basic form of files in the source directory matching *-fid*.
For each name found, assign the name to filename and execute the :process routine, which first removes the characters up to and including -fid from filename then uses the delims=- option to assign the part originally between -fid and the following - to %%q.
setthe variable $%%q up by 1 (if $?? is undefined, assign 1)
Finally, when all the names have been processed, list the variables named $... using set which produces a report of the style
$1000=2
$2000=3
Using $ and = as delimiters puts token 1 (eg 2000) into %%a and token 2 (eg 3) into %%b. Write these to the output using echo, remembering to escape the pipe (|) with a caret (^) to suppress the interpretation as a redirector.
The parentheses around the for...$... ensures the output is directed to the destination file specified.
Extract the numbers into a temporary file, then count the occurrences of each number in that file.
#echo off
setlocal EnableDelayedExpansion
>temp.txt type nul
set "unique_num="
for /f "tokens=2 delims=-" %%a in ('dir /b *.dat') do (
set "fid=%%a"
set "num=!fid:~3!"
>>temp.txt echo !num!
echo " !unique_num! " | find " !num! " >nul
if !errorlevel! neq 0 set "unique_num=!unique_num! !num!"
)
for %%n in (%unique_num%) do (
for /f "delims=: tokens=2" %%c in ('find /c "%%n" temp.txt') do (
set "count=%%c"
echo %%n^|!count: =!
)
)
del /f /q temp.txt
Pipe the result into sort if you need the output sorted.
Related
#echo off
ren "(1) Rare Imports Exclusive.txt" "1RareImportsExclusive.txt"
set "replace="unid": 0,"
set "replaced="unid": 1,"
set "source=1RareImportsExclusive.txt"
set "target=1RareImportsExclusive1.txt"
setlocal enableDelayedExpansion
(
for /F "tokens=1* delims=:" %%a in ('findstr /N "^" %source%') do (
set "line=%%b"
if defined line set "line=!line:%replace%=%replaced%!"
echo(!line!
)
) > %target%
ren "1RareImportsExclusive1.txt" "(1) Rare Imports Exclusive.txt"
del "1RareImportsExclusive.txt"
endlocal
I have update my Original Post
I have over 1000 .txt files, and in the content of each file has a UNID code
with random numbers
My goal is to have 1 bat file that can ignore all random numbers and
rename the unid based on the file number
Original files
(1) Rare Imports Exclusive.txt
------- "unid": 2548,"
Outcome files
(1) Rare Imports Exclusive.txt
------- "unid": 1,"
I can only get this to work if I change all unid to 0,
and if I make 1000 .bat files
So I make as many batch files and merge them
This works for now
#ECHO Off
setlocal ENABLEDELAYEDEXPANSION
set "replacemain="unid": "
SET "sourcedir=u:\sourcedir\t w o"
SET "destdir=u:\destdir"
FOR /f "delims=" %%q IN ('dir /b /a-d "%sourcedir%\(*)*.txt"') DO (
(
FOR /f "tokens=1 delims=()" %%j IN ("%%q") DO (
rem %%j now has sequence number
for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "%sourcedir%\%%q"') do (
set "line=%%b"
if defined line IF "%%b" neq "!line:unid=!" CALL :subs %%j
echo(!line!
)
)
)>"%destdir%\%%q"
)
GOTO :eof
:: substitute
:subs
SET "original=%line%"
FOR /L %%s IN (0,1,9) DO set "line=!line:%replacemain%%%s=%replacemain%!"
IF "%original%" neq "%line%" goto subs
set "line=!line:%replacemain%=%replacemain%%1!"
GOTO :eof
As I read it, this problem has nothing to do with renaming files, but changing their contents.
You would need to change the settings of sourcedir and destdir to suit your circumstances. The listing uses a setting that suits my system.
I deliberately include spaces in names to ensure that they are processed correctly.
So, assuming that the filenames in the source directory follow the pattern (?) filename.txt and the required work is to replace the string "unid": ##, with "unid": ?, (where ## is a random number and ? is the number from the filename...
Grab the filenames to %%q and derive the filenumber to %%j.
Read and regurgitate. Detect whether the line contains unid etc. and further process these using :subs.
In :subs, replace the unid,etc. string followed by a digit by the string without the digit. If any change was made, repeat. Then substitute %%j passed as %1 to the :subs routine.
--- Revision for including subdirectories.
#ECHO Off
setlocal ENABLEDELAYEDEXPANSION
:: Significant part of string
set "replacemain="unid": "
SET "sourcedir=u:\your files"
SET "destdir=u:\your results"
FOR /f "delims=" %%q IN ('dir /b /s /a-d "%sourcedir%\(*)*.txt"') DO (
rem calculate new destination directory
SET "newdest=%%~dpq"
SET "newdest=!newdest:%sourcedir%=%destdir%!"
SET "newdest=!newdest:~0,-1!"
MD "!newdest!" 2>nul
(
FOR /f "tokens=1 delims=()" %%j IN ("%%~nxq") DO (
rem %%j now has sequence number
for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "%%q"') do (
set "line=%%b"
if defined line IF "%%b" neq "!line:unid=!" CALL :subs %%j
echo(!line!
)
)
)>"!newdest!\%%~nxq"
)
GOTO :eof
:: substitute
:subs
SET "original=%line%"
FOR /L %%s IN (0,1,9) DO set "line=!line:%replacemain%%%s=%replacemain%!"
IF "%original%" neq "%line%" goto subs
set "line=!line:%replacemain%=%replacemain%%1!"
GOTO :eof
You would need to change the values assigned to sourcedir and destdir to suit your circumstances. The listing uses a setting that suits my system.
I deliberately include spaces in names to ensure that the spaces are processed correctly.
First, addition of /s in the dir command to cause scanning of subdirectories. This means that %%q will contain the absolute filename of each file that fits the mask (*)*.txt.
Since the destination directory may now change, newdest is calculated by replacing the value of sourcedir with the value of destdir and removing the final \ character since %%~dpq will deliver a \-terminated string.
The directory thus calculated is then created with a md instruction, and any objection from the system (as it's likely the directory already exists) is discarded with 2>nul (send error messages nowhere).
Since %%q originally contained the filename only, we need to specifically select the name and extension of %%q (%%~nxq) when calculating %%j.
Since %%q contains the absolute filename, we remove the %sourcedir% from the file-read loop using %%a.
Finally, the destination file needs to be constructed from the calculated newdest and the name+extension of the sourcefile.
--- Re-revision
#ECHO Off
setlocal ENABLEDELAYEDEXPANSION
:: Significant part of string
set "replacemain="unid": "
SET "sourcedir=u:\your files"
SET "destdir=u:\your results"
:: for tracking directory-changes
SET "lastdir="
SET /a serial=1
FOR /f "delims=" %%q IN ('dir /b /s /a-d "%sourcedir%\(*)*.txt"') DO (
rem use following line to restart serial number for each file
REM SET /a serial=1
if "!lastdir!" neq "%%~dpq" (
rem use following line to restart serial number for each directory
REM SET /a serial=1
rem calculate new destination directory
SET "newdest=%%~dpq"
SET "lastdir=%%~dpq"
SET "newdest=!newdest:%sourcedir%=%destdir%!"
SET "newdest=!newdest:~0,-1!"
MD "!newdest!" 2>NUL
)
(
rem %%j will acquire sequence number for filename pattern (*)*.txt
REM FOR /f "tokens=1 delims=()" %%j IN ("%%~nxq") DO SET "serial=%%j"
rem use following line to select a random serial number for each file
REM CALL :randsn
for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "%%q"') do (
set "line=%%b"
if defined line IF "%%b" neq "!line:unid=!" CALL :subs
echo(!line!
)
)>"!newdest!\%%~nxq"
)
GOTO :eof
:: substitute
:subs
SET "original=%line%"
FOR /L %%s IN (0,1,9) DO set "line=!line:%replacemain%%%s=%replacemain%!"
IF "%original%" neq "%line%" goto subs
set "line=!line:%replacemain%=%replacemain%%serial%!"
SET /a serial+=1
GOTO :eof
:randsn
SET /a serial=%RANDOM%
:: Ignore selections 30000..32767 for even distribution
IF %serial% geq 30000 GOTO randsn
:: Use 10000 for 4-digit maximum, 1000 for 3, 100 for 2
SET /a serial=serial %% 10000
:: Use the following line if 0 is not allowed
IF %serial%==0 GOTO randsn
GOTO :eof
This provides a choice of how the number is calculated.
To activate any particular option, change the REM in the line following the comment to (nothing). It would probably be insane to try to activate more than one option at any one time. To deselect an option, put the REM keyword back in place.
The random option will generate a random 1-4-digit number. There is absolutely no guarantee whatever that the numbers inserted in this case will be unique.
To allow the routine to operate on any file in the tree, simply change the filemask (*)*.txt to some other filemask, noting that the derivation of sequence number for filenames that do not start (number) via %%j would then become nonsense, so the setting of serial from %%j should be de-activated with a rem statement (as posted)
I have two files :
old_names.txt
oldname1
oldname2
new_names.txt
newname1
newname2
I would like to search my folder for file names containing "old_names" and replace "old_name" string with corresponding "new_name".
for /f %%i in (old_names.txt) do (
// get corresponding %%j new_name
for /f %%a in ('dir /b /a-d *%%i*') do ren %%a %%j
)
How can I retrieve the corresponding new_name ?
For your file pair concept you basically need to read the two files line by line simultaneously, if I understand correctly, which can be accomplished like illustrated in this answer. So here is a possible code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=D:\path\to\root_dir" & rem // (directory containing files to rename)
set "_FILE1=D:\path\to\old_names.txt"
set "_FILE2=D:\path\to\new_names.txt"
rem // Count number of lines of 1st file (2nd file is not checked):
for /F %%C in ('^< "%_FILE1%" find /C /V ""') do set "NUM1=%%C"
setlocal EnableDelayedExpansion
rem // Change into root directory:
cd /D "%_ROOT%" || exit /B 1
rem // Here input redirection is used to read both files simultaneously:
9< "!_FILE1!" 8< "!_FILE2!" (
rem // Loop through the number of lines of the 1st file:
for /L %%I in (1,1,%NUM1%) do (
rem // Read a line from the 1st file:
<&9 (set "LINE1=" & set /P "LINE1=")
rem // Read a line from the 2nd file:
<&8 (set "LINE2=" & set /P "LINE2=")
rem /* Assign line strings to `for` variables to later avoid nested
rem delayedly expanded environment variables: */
for /F "tokens=1,2 delims=| eol=|" %%I in ("!LINE1!|!LINE2!") do (
rem // Get list of files matching the partial name:
for /F "delims= eol=|" %%F in ('dir /B /A:-D "*!LINE1!*"') do (
endlocal
rem // Store current file name:
set "NAME=%%F"
setlocal EnableDelayedExpansion
rem // Do the actual sub-string replacement and rename file:
ECHO ren "!NAME!" "!NAME:%%I=%%J!"
)
)
)
)
endlocal
endlocal
exit /B
After having checked the correct output, remove the upper-case ECHO command!
This does not work if any of the following characters occur in the two name files: =, !, ^; the ~ must not occur as the first character in any line of the first file (old names).
As per my comment. Create a single file called names.txt and add the strings you want to replace and what you want to replace it with:
dummy replacement
dummy2 replacement2
then the script needs to be in the same directory, or you have to specify path to the files:
#echo off
setlocal enabledelayedexpansion
for /f "tokens=1,2" %%i in (names.txt) do (
for /f %%a in ('dir /b /a-d ^| findstr "%%i"') do (
set "oldname=%%a"
set "newname=!oldname:%%i=%%j!"
echo ren "!oldname!" "!newname!"
)
)
or by specifying path:
#echo off
setlocal enabledelayedexpansion
for /f "tokens=1,2" %%i in (names.txt) do (
for /f %%a in ('dir /b /a-d "D:\PATH" ^| findstr "%%i"') do (
set "oldname=%%a"
set "newname=!oldname:%%i=%%j!"
echo ren "!oldname!" "!newname!"
)
)
Once you are happy that it prints the files to replace to screen, simply remove the echo from the last line of code to actually perform the ren
This is my first posting so if the format is not as it supposed to be please excuse me for this. (Suggestions for
improvement are welcome.)
I am trying to create a batchfile that will read last lines from logfiles and copy them to a new file.
Until now I have found here a way to read the last line.
Code would be something like:
for /f %%i in ('find /v /c "" ^< someFile.txt') do set /a lines=%%i
set /a startLine=%lines% - 1
more /e +%startLine% someFile.txt > lastLines.txt
The above code works for one file at a time. What I need is to read the last line from all files in a known list and add this line to a new .csv file.
I have been using the following code for getting the 4th entry in the logfiles but it returns every line of every logfile:
for /f %%x in (%list%) do for /f "delims=.txt, tokens=4" %%i in (%%x.txt) do echo %%x, %%i >> output.csv
What I would need is a sort of combination of both but I don't know how to combine them and make the complete last line be copied to the .csv file.
===
#Magoo:
Thanx for your reaction.
In every logfile can be 1 to >100 lines with comma separated information. Something like:
"LOGON,6-1-2015,12:43:39,USERNAME,HOSTNAME,,,,192.168.209.242,00:21:5A:2E:64:5E"
The last code with the 4th entry was used to get a list of all accounts that had logged in to the computers. This code gave me a very large list of all logon/logoff events on all computerlogs I checked in %list%.
In %list$ I had all the names of logfiles I wanted to be checked. This returned all lines.
For a new batchfile I need only the last logon/logoff entry and I want the whole last line.
So I have a .txt file with the hostnames of all computers I need to examine.
This .txt file will be read line by line via the variable %list%.
From every logfile I need only the last line copied to an output file.
===
I just tried the solution offered by JosefZ. Unfortunately this does not work for me yet. No lastlines are copied to the resultfile. In the code I removed the extra entry for possible lastlines for there are no empty lines in the logs, I also added an entry for the hostname I want to be available in the result. JosefZ had the filename there:
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
type nul>output.csv
set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
set "host=%%~x"
for /F "tokens=*" %%G in ('type "%%~x"') do set "lastline=%%G"
call :lline
)
:endlocal
#ENDLOCAL
goto :eof
:lline
set "filename=.\logs\%filename:&=^&%.txt"
echo %host%,%lastline%>>output.csv
goto :eof
The resultfile shows only the hostnames. I'll puzzle some more with this but all tips are welcome!
===
Got it!!!
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
type nul>output.csv
set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
set filename= :: *empty previous filename*
set lastline= :: *empty previous lastline*
set "host=%%~x"
set "filename=.\logs\%host%.txt" :: *creating the filename from path+hostname+extention*
for /F "tokens=*" %%G in ('type "%filename%"') do set "lastline=%%G"
call :lline
)
:endlocal
#ENDLOCAL
goto :eof
:lline
echo %host%,%lastline%>>output.csv
goto :eof
Your approach with line numbering could fail if a file has more trailing empty lines. Fortunately for /F loop ignores (does not iterate) empty lines; let's put to use this feature: in the script used next practices:
disabledelayedexpansion to allow ! in file names
set "list=_listing.txt" where the _listing.txt contains list of file names (full path and extension .txt including), one file name on one line: got by dir /b /s *.txt>_listing.txt
type nul>files\output.csv to empty the output file (optional)
set "lastline=!!!file empty!!!" to initialize variable %lastline%; could be set "lastline=" as well
call :lline to process variables %filename% and %lastline%
set "filename=%filename:&=^&%" to allow & in file names
The script is as follows:
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
type nul>files\output.csv
set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
set "filename=%%~x"
set "lastline=!!!file empty!!!"
rem the whole line
for /F "tokens=*" %%G in ('type "%%~x"') do set "lastline=%%G"
rem the fourth token only
rem for /F "tokens=4" %%G in ('type "%%~x"') do set "lastline=%%G"
call :lline
)
:endlocal
#ENDLOCAL
goto :eof
:lline
set "filename=%filename:&=^&%"
echo %filename% %lastline%
rem >>files\output.csv
goto :eof
Sample _listing.txt file:
d:\bat\files\1exclam!ation.txt
d:\bat\files\2exc!lam!ation.txt
d:\bat\files\11per%cent.txt
d:\bat\files\12per%cent%.txt
d:\bat\files\17per%Gcent.txt
d:\bat\files\18per%%Gcent.txt
d:\bat\files\21ampers&nd.txt
d:\bat\files\22ampers&&nd.txt
Output:
d:\bat>lastlines
d:\bat\files\1exclam!ation.txt 0 15.01.2015 1:52:28.48 -15072 20465
d:\bat\files\2exc!lam!ation.txt 6 15.01.2015 1:52:28.50 3250 16741
d:\bat\files\11per%cent.txt -8 15.01.2015 1:52:28.50 -3692 27910
d:\bat\files\12per%cent%.txt !!!file empty!!!
d:\bat\files\17per%Gcent.txt 0 15.01.2015 1:52:28.56 14508 12374
d:\bat\files\18per%%Gcent.txt 1 15.01.2015 1:52:28.56 30540 26959
d:\bat\files\21ampers&nd.txt 15.01.2015 1:22:50.18
d:\bat\files\22ampers&&nd.txt 15.01.2015 1:22:50.18
Honestly, all that ballast is for (possibly) trailing empty lines in files and for (possibly) ! and & in file names only; all could be done with
for /f %%x in (%list%) do for /f "skip=%startLine% tokens=4" %%i in (%%x) do echo %%x, %%i >> output.csv
You should use a simple FOR to iterate a list of values, not FOR /F.
Something like the following should work:
#echo off
setlocal enableDelayedExpansion
>>output.csv (
for %%F in (
"file1.log"
"file2.log"
"file3.log"
etc.
) do (
for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
more +!skip! %%F
)
)
The quotes around the file names are there in case you get a name with spaces.
You could use your LIST variable if it looks something like
set LIST="file1.log" "file2.log" "file3.log" etc.
#echo off
setlocal enableDelayedExpansion
set LIST="file1.log" "file2.log" "file3.log" etc.
>>output.csv (
for %%F in (%LIST%) do (
for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
more +!skip! %%F
)
)
If any of your file names contain the ! character, then you must toggle delayed expansion ON and OFF within your loop. Otherwise the delayed expansion will corrupt the names when %%F is expanded.
#echo off
setlocal disableDelayedExpansion
set LIST="file1.log" "file2.log" "file3.log" etc.
>>output.csv (
for %%F in (%LIST%) do (
for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
setlocal enableDelayedExpansion
more +!skip! %%F
endlocal
)
)
I am trying to modify a batch file created by somebody else, to add leading zeros depending on the number found on line 4 of the file. The actual filename is a concatenation of the name found on line 3, and the numbers on line 4. So if the first few lines are as follows:
3.1.19
-1
TEST
560
The file name would be v_TEST00560.TXT. As you can see, the total number of digits in the file name should be 5. If the number which appears on line 4 is 8 (see below), then:
3.1.19
-1
TEST
8
The file name will be v_TEST00008.txt.
The file I have is as follows:
#Echo Off
Setlocal EnableDelayedExpansion
REM File: rename5.bat
REM The script will look for and parse one (or more) input files
REM Input files can containrecords for one or more vessels.
REM This script assumes that each record starts with the "3.1.19" string.
REM %%%%%%%%%%%%%%%%%%%%%%% Configuration Section %%%%%%%%%%%%%%%%%%%%%%%
SET INPUT_DIR=C:\Files\RenameFileName\Input
SET OUTPUT_DIR=C:\Files\RenameFileName\Output
SET ARCHIVE_DIR=C:\Files\RenameFileName\Archive
SET TEMP_DIR=C:\Files\RenameFileName\tmp
SET INPUT_FILENAME=INTERFACE.TXT
SET REC=3.1.19
REM %%%%%%%%%%%%%%%%%%%%%%%%%%%% Checking Section %%%%%%%%%%%%%%%%%%%%%%%%%%%%
FOR /F "usebackq tokens=* eol= delims= " %%d IN (`date /t`) do SET RUNDATE=%%d
echo [%RUNDATE% %TIME%] Script starting...
IF NOT EXIST %INPUT_DIR% (
SET MESSAGE=Input directory not found.
goto END
)
IF NOT EXIST %OUTPUT_DIR% (
SET MESSAGE=Output directory not found.
goto END
)
IF NOT EXIST %ARCHIVE_DIR% (
SET MESSAGE=Archive directory not found.
goto END
)
IF NOT EXIST %TEMP_DIR% (
echo Temporary directory does not exit.
echo Creating %TEMP_DIR%
mkdir %TEMP_DIR%
)
REM %%%%%%%%%%%%%%%%%%%%%%%%% Main Processing %%%%%%%%%%%%%%%%%%%%%%%%%
dir %INPUT_DIR%\%INPUT_FILENAME% 1>NUL 2>NUL
IF %ERRORLEVEL% EQU 1 (
SET MESSAGE=Input files not present.
goto END
)
FOR /F "usebackq tokens=* eol= delims= " %%d IN (`date /t`) do SET RUNDATE=%%d
echo [%RUNDATE% %TIME%] Input files found. Start Processing...
FOR /F "usebackq" %%I IN (`dir /b %INPUT_DIR%\%INPUT_FILENAME%`) DO (
SET INPUT_FILE=!INPUT_DIR!\%%I
echo READING Input file: !INPUT_FILE!
SET N=
FOR /F "tokens=* eol= delims= " %%A IN (!INPUT_FILE!) Do (
set LINE=%%A
set LINE2=!LINE:~0,6!
if !LINE2! EQU !REC! (
SET /A N+=1
echo Creating temp file !TEMP_DIR!\!N!.tmp
)
echo !LINE! >> !TEMP_DIR!\!N!.tmp
)
FOR /F "usebackq" %%Y in (`dir /b !TEMP_DIR!\*.tmp`) DO (
SET TEMPFILE=!TEMP_DIR!\%%Y
SET N=
FOR /F %%A IN (!TEMPFILE!) DO (
SET /A N+=1
IF !N! EQU 3 SET S=%%A
IF !N! EQU 4 SET T=%%A
)
SET S=!S:~0,10!
SET T=!T:~0,10!
echo CREATING Output File: %OUTPUT_DIR%\V_!S!00!T!.TXT
MOVE !TEMPFILE! %OUTPUT_DIR%\V_!S!00!T!.TXT
)
)
REM %%%%%%%%%%%%%%%%%%%%%%%%% Archiving Section %%%%%%%%%%%%%%%%%%%%%%%%%
FOR /F "usebackq" %%t IN (`cscript "%~dp0timestamp.vbs" //Nologo`) do SET TIMESTAMP=%%t
FOR /F "usebackq" %%I IN (`dir /b %INPUT_DIR%\%INPUT_FILENAME%`) DO (
echo ARCHIVING Input file %%I to %ARCHIVE_DIR%
rem COPY !INPUT_DIR!\%%I !ARCHIVE_DIR!\%%I.!TIMESTAMP!
MOVE !INPUT_DIR!\%%I !ARCHIVE_DIR!\%%I.!TIMESTAMP!
)
REM %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FOR /F "usebackq tokens=* eol= delims= " %%d IN (`date /t`) do SET RUNDATE=%%d
SET MESSAGE=[%RUNDATE% %TIME%] Processing Done.
:END
echo %MESSAGE%
FOR /F "usebackq tokens=* eol= delims= " %%d IN (`date /t`) do SET RUNDATE=%%d
echo [%RUNDATE% %TIME%] Script finished.
As you can see, its quite sophisticated, and I have no idea how to make these changes myself. The BAT runs perfectly, but the number of zeroes if fixed, and not generated depending on the number of digits already present. Any help appreciate
I'm not about to read all of your code, but I use this for padding zeros.
The first line is whetever number you read from your file.
The second line pads more than enough zeros to the start of the variable.
The third line cuts off all but the last five characters from the variable.
Set Number=123
Set Number=00000%Number%
Set Number=%Number:~-5%
I have successfully made a script that filters out duplicate lines in a file and saves the results to a variable semi-colon separated (sort of an "array"). I could not find any real good solution to it.
#echo off
setlocal enabledelayedexpansion
rem test.txt contains:
rem 2007-01-01
rem 2007-01-01
rem 2007-01-01
rem 2008-12-12
rem 2007-01-01
rem 2009-06-06
rem ... and so on
set file=test.txt
for /f "Tokens=* Delims=" %%i in ('type %file%') do (
set read=%%i
set read-array=!read-array!;!read!
)
rem removes first trailing ";"
set read-array=!read-array:*;=!
echo !read-array!
for /f "Tokens=* Delims=" %%i in ('type %file%') do (
set dupe=0
rem searches array for the current read line (%%i) and if it does exist, it deletes ALL occurences of it
echo !read-array! | find /i "%%i" >nul && set dupe=1
if ["!dupe!"] EQU ["1"] (
set read-array=!read-array:%%i;=!
set read-array=!read-array:;%%i=!
)
rem searches array for the current read line (%%i) and if it does not exist, it adds it once
echo !read-array! | find /i "%%i" >nul || set read-array=!read-array!;%%i
)
rem results: no duplicates
echo !read-array!
Contents of !read-array! is 2008-12-12;2007-01-01;2009-06-06
I now want to take out each item in the array and write them to a new file, with line breaks after each item. Example:
2008-12-12
2007-01-01
2009-06-06
So this is what I've come up with so far.
The problem I'm having is that the second for-loop doesn't accept the !loop! variable as a token definition when being nested. It does however accept %loop% if it's not nested.
The reason I'm doing it this way is that the !read-array! may have a unknown number of items, therefore I count them as well.
Any ideas?
rem count items in array
set c=0
for %%i in (!read-array!) do set /a c+=1
echo %c% items in array
for /l %%j in (1,1,%c%) do (
set loop=%%j
for /f "Tokens=!loop! Delims=;" %%i in ("!read-array!") do (
echo %%i
rem echo %%i>>%file%
)
)
exit /b
At end of your first section, when contents of !read-array! is 2008-12-12;2007-01-01;2009-06-06, you may directly separate the elements of your "list" with a simple for because the standard separators in Batch files may be, besides spaces, comma, semicolon or equal signs:
for %%i in (%read-array%) do echo %%i
However, may I suggest you a simpler method?
Why not define a "real" array with the subscript value of the lines? This way, several repeated lines will store its value in the same array element. At end, just display the values of the resulting elements:
#echo off
set file=test.txt
for /F "Delims=" %%i in (%file%) do (
set read-array[%%i]=%%i
)
rem del %file%
for /F "Tokens=2 Delims==" %%i in ('set read-array[') do (
echo %%i
rem echo %%i>>%file%
)
EDIT
Alternative solution
There is another method that assemble a list of values separated by semicolon as you proposed. In this case each value is first removed from previous list content and immediately inserted again, so at end of the cycle each value is present just once.
#echo off
setlocal EnableDelayedExpansion
set file=test.txt
for /F "Delims=" %%i in (%file%) do (
set read-array=!read-array:;%%i=!;%%i
)
rem del %file%
for %%i in (%read-array%) do (
echo %%i
rem echo %%i>> %file%
)