Link to home
Start Free TrialLog in
Avatar of InvoiceInsight
InvoiceInsight

asked on

Batch script to count total files by date and directory

I am trying to create a batch script that will provide some rudimentary reporting on the number of files that are placed in directories on a daily basis, weekly and monthly basis.  The script will be scheduled to run after hours using windows scheduler.  

For example:

If today's date is the 9-18-2007

If these are my files\directories:

d:\test\group1\cust1\9-17-07\file1
d:\test\group1\cust2\9-17-07\file1
d:\test\group1\cust1\9-18-07\file1
d:\test\group1\cust2\9-18-07\file1
d:\test\group1\cust2\9-18-07\file2
d:\test\group2\cust1\9-17-07\file1
d:\test\group2\cust2\9-17-07\file1
d:\test\group2\cust1\9-18-07\file1
d:\test\group2\cust2\9-18-07\file1
d:\test\group2\cust2\9-18-07\file2

I need a daily report that would tell me that a total of 6 new files were created this day, 2 for cust1 and 4 for cust 2

I need a weekly report that would tell me that the total number of files created for the week was 10, and detail the number of files per customer.

Same this for my monthly report.

I have logic that can determine the date already and I can get a listing of the number of files per directory, but I am stumped on how to get the subtotals and totals I am looking for.

Here is what I have so far (this example is for the "daily" report):

The output from the script below looks like this:

"E:\test\group1\cust1\09-17-07\file1"=1
"E:\test\group1\cust1\09-18-07\file1"=1
"E:\test\group1\cust2\09-17-07\file1"=1
"E:\test\group1\cust2\09-18-07\file1"=1
"E:\test\group1\cust2\09-18-07\file2"=1

@echo off

setlocal

set srcDir=E:\test
set dirMask=*.*

if not "%1"=="" set srcDir=%1

if not exist "%srcDir%" echo Directory %srcDir% does not exist.&goto :EOF

call :GETPARTS "%date%

call :SUBTRACTDAYS 1

set cutoffDate=%yy%/%mm%/%dd%

pushd.

cd /D %srcDir%

for /f "delims=" %%a in ('dir /b /a-d /S %dirMask%') do call :PROCESS "%%a" %%~ta

popd

goto :EOF

:PROCESS

call :GETPARTS %2

REM ================================================================================
REM This is where I get the totals for each directory, but I can seem to add them up
REM ================================================================================
if /i "%cutoffDate%" GTR "%yy%/%mm%/%dd%" dir %1
FOR /F "TOKENS=1" %%F IN ('DIR %1 /S^|FIND /i "file(s)"') DO (SET TOTAL=%%F)
Echo %1=%TOTAL%
REM ================================================================================

goto :EOF

:SUBTRACTDAYS

set dayCnt=%1

if "%dayCnt%"=="" set dayCnt=1

REM Substract your days here
set /A dd=1%dd% - 100 - %dayCnt%
set /A mm=1%mm% - 100

:CHKDAY

if /I %dd% GTR 0 goto DONESUBTRACT

set /A mm=%mm% - 1

if /I %mm% GTR 0 goto ADJUSTDAY

set /A mm=12
set /A yy=%yy% - 1

:ADJUSTDAY

if %mm%==1 goto SET31
if %mm%==2 goto LEAPCHK
if %mm%==3 goto SET31
if %mm%==4 goto SET30
if %mm%==5 goto SET31
if %mm%==6 goto SET30
if %mm%==7 goto SET31
if %mm%==8 goto SET31
if %mm%==9 goto SET30
if %mm%==10 goto SET31
if %mm%==11 goto SET30
REM ** Month 12 falls through

:SET31

set /A dd=31 + %dd%

goto CHKDAY

:SET30

set /A dd=30 + %dd%

goto CHKDAY

:LEAPCHK

set /A tt=%yy% %% 4

if not %tt%==0 goto SET28

set /A tt=%yy% %% 100

if not %tt%==0 goto SET29

set /A tt=%yy% %% 400

if %tt%==0 goto SET29

:SET28

set /A dd=28 + %dd%

goto CHKDAY

:SET29

set /A dd=29 + %dd%

goto CHKDAY

:DONESUBTRACT

if /I %mm% LSS 10 set mm=0%mm%
if /I %dd% LSS 10 set dd=0%dd%

goto :EOF

:GETPARTS

set dt=%~1
set tok=1-3

if "%dt:~0,1%" GTR "9" set tok=2-4

set yyyy=

for /f "tokens=%tok% delims=.:/-, " %%a in ('echo %~1') do (
  for /f "skip=1 tokens=2-4 delims=/-,()." %%x in ('echo.^|date') do set %%x=%%a&set %%y=%%b&set %%z=%%c
)

if not "%yyyy%"=="" set yy=%yyyy%

if 1%yy% LSS 1000 (if %yy% LSS 70 (set yy=20%yy%) else (set yy=19%yy%))
if 1%mm% LSS 100 set mm=0%mm%
if 1%dd% LSS 100 set dd=0%dd%

goto :EOF
Avatar of Zvonko
Zvonko
Flag of North Macedonia image

Lern WindowsScriptingHost (WSH) and your life gets easy.
Upper code is much shrter and readable in VBScript or JavaScript. Which one would you prefer to start with?
Here a link for WSH starters: http://msdn2.microsoft.com/en-us/library/ms950396.aspx
Here's some code to get the daily report:

@echo off

setlocal

set srcDir=c:\test
set dirMask=*.*

if not "%1"=="" set srcDir=%1

if not exist "%srcDir%" echo Directory %srcDir% does not exist.&goto :EOF

call :GETDATEPARTS "%date%

set cutoffDate=%yy%%mm%%dd%

set /a totalCnt=0

set outFile=%~0.out

pushd "%srcDir%"

if exist "%outFile%" del "%outFile%"

for /f "tokens=*" %%a in ('dir /b /a-d /S "%dirMask%"') do call :PROCESS "%%a" %%~ta

if not exist "%outFile%" echo Did not find any files to processing&goto CLEANUP

echo Total files: %totalCnt%

sort "%outFile%">"%~0.srt"

set lastKey=

set /a totalCnt=0

for /f "tokens=*" %%a in ('type "%~0.srt"') do call :TALLYCUST "%%a"

call :TALLYCUST

:CLEANUP

if exist "%outFile%" del "%outFile%"
if exist "%~0.srt" del "%~0.srt"

popd

goto :EOF

:TALLYCUST

if "%~1"=="%lastKey%" set /a totalCnt+=1&goto :EOF

if not "%lastKey%"=="" echo Total for %lastKey%: %totalCnt%

set lastKey=%~1

set /a totalCnt=1

goto :EOF

:PROCESS

set cust=

for /f "tokens=4 delims=\" %%a in ('echo %~1') do set cust=%%a

if "%cust%"=="" goto :EOF

call :GETDATEPARTS %2

if /i "%cutoffDate%" NEQ "%yy%%mm%%dd%" goto :EOF

echo %cust%>>"%outFile%"

set /a totalCnt+=1

goto :EOF

:GETDATEPARTS

set dt=%~1
set tok=1-3

if "%dt:~0,1%" GTR "9" set tok=2-4

set yyyy=

for /f "tokens=%tok% delims=.:/-, " %%a in ('echo %~1') do (
  for /f "skip=1 tokens=2-4 delims=/-,()." %%x in ('echo.^|date') do set %%x=%%a&set %%y=%%b&set %%z=%%c
)

if not "%yyyy%"=="" set yy=%yyyy%

if 1%yy% LSS 1000 (if %yy% LSS 70 (set yy=20%yy%) else (set yy=19%yy%))
if 1%mm% LSS 100 set mm=0%mm%
if 1%dd% LSS 100 set dd=0%dd%

goto :EOF
Avatar of InvoiceInsight
InvoiceInsight

ASKER

SteveGTR - Absolutley fabulous..  Works great - Can you tell me what paramter I need to change to change to include 7 days or 30 days wirth of files?

Great work!
Ah, that's why you had the subtract days routine in the code. That implementation makes it much easier. I'll add it back and get this fixed up. Please stand by :)
Give this a try. The processing can accept two parameters. 1st being the directory and the 2nd being the number of days to set date to. If no 2nd parameter is specified, the processing will prompt you:

@echo off

setlocal

set srcDir=E:\test
set dirMask=*.*

if not "%1"=="" set srcDir=%1

if not exist "%srcDir%" echo Directory %srcDir% does not exist.&goto :EOF

set freq=

if not "%~2"=="" set freq=%~2

if "%freq%"=="" set /p freq=Enter number of days to run processing for:

if "%freq%"=="" echo Processing aborted&goto :EOF

call :GETDATEPARTS "%date%"
call :SUBTRACTDAYS %freq%

set cutoffDate=%yy%%mm%%dd%

set /a totalCnt=0

set outFile=%~0.out

pushd "%srcDir%"

if exist "%outFile%" del "%outFile%"

for /f "tokens=*" %%a in ('dir /b /a-d /S "%dirMask%"') do call :PROCESS "%%a" %%~ta

if not exist "%outFile%" echo Did not find any files to processing&goto CLEANUP

echo Total files updated in the last %freq% day(s): %totalCnt%

sort "%outFile%">"%~0.srt"

set lastKey=

set /a totalCnt=0

for /f "tokens=*" %%a in ('type "%~0.srt"') do call :TALLYCUST "%%a"

call :TALLYCUST

:CLEANUP

if exist "%outFile%" del "%outFile%"
if exist "%~0.srt" del "%~0.srt"

popd

goto :EOF

:TALLYCUST

if "%~1"=="%lastKey%" set /a totalCnt+=1&goto :EOF

if not "%lastKey%"=="" echo Total for %lastKey%: %totalCnt%

set lastKey=%~1

set /a totalCnt=1

goto :EOF

:PROCESS

set cust=

for /f "tokens=4 delims=\" %%a in ('echo %~1') do set cust=%%a

if "%cust%"=="" goto :EOF

call :GETDATEPARTS %2

if /i "%cutoffDate%" GTR "%yy%%mm%%dd%" goto :EOF

echo %cust%>>"%outFile%"

set /a totalCnt+=1

goto :EOF

:GETDATEPARTS

set dt=%~1
set tok=1-3

if "%dt:~0,1%" GTR "9" set tok=2-4

set yyyy=

for /f "tokens=%tok% delims=.:/-, " %%a in ('echo %~1') do (
  for /f "skip=1 tokens=2-4 delims=/-,()." %%x in ('echo.^|date') do set %%x=%%a&set %%y=%%b&set %%z=%%c
)

if not "%yyyy%"=="" set yy=%yyyy%

if 1%yy% LSS 1000 (if %yy% LSS 70 (set yy=20%yy%) else (set yy=19%yy%))
if 1%mm% LSS 100 set mm=0%mm%
if 1%dd% LSS 100 set dd=0%dd%

goto :EOF

:SUBTRACTDAYS

set dayCnt=%~1

if "%dayCnt%"=="" set dayCnt=1

REM Substract your days here
set /A dd=1%dd% - 100 - %dayCnt%
set /A mm=1%mm% - 100

:CHKDAY

if /I %dd% GTR 0 goto DONESUBTRACT

set /A mm=%mm% - 1

if /I %mm% GTR 0 goto ADJUSTDAY

set /A mm=12
set /A yy=%yy% - 1

:ADJUSTDAY

if %mm%==1 goto SET31
if %mm%==2 goto LEAPCHK
if %mm%==3 goto SET31
if %mm%==4 goto SET30
if %mm%==5 goto SET31
if %mm%==6 goto SET30
if %mm%==7 goto SET31
if %mm%==8 goto SET31
if %mm%==9 goto SET30
if %mm%==10 goto SET31
if %mm%==11 goto SET30
REM ** Month 12 falls through

:SET31

set /A dd=31 + %dd%

goto CHKDAY

:SET30

set /A dd=30 + %dd%

goto CHKDAY

:LEAPCHK

set /A tt=%yy% %% 4

if not %tt%==0 goto SET28

set /A tt=%yy% %% 100

if not %tt%==0 goto SET29

set /A tt=%yy% %% 400

if %tt%==0 goto SET29

:SET28

set /A dd=28 + %dd%

goto CHKDAY

:SET29

set /A dd=29 + %dd%

goto CHKDAY

:DONESUBTRACT

if /I %mm% LSS 10 set mm=0%mm%
if /I %dd% LSS 10 set dd=0%dd%

goto :EOF
Thank you for all the time and effort you have put into this.  

one last thing - since the script was changed, I am now getting an error when running it

".txt') was unexpected at this time."

Is this because the files in the directory have extensions?
Hard to say. None of my changes should produce this error.

Have you changed the script from what I posted?

How are you running the script?

Can you run the old version to see if the error happens?

Can you run new version with the @echo off command remarked out and see where the error occurs?

REM @echo off
I have not modified your script.  Here is the ouput with echo turned on.

E:\test1>call :PROCESS "E:\test1\New Text Document (2).txt" 09/21/2007 04:44 PM


E:\test1>set cust=
.txt') was unexpected at this time.
E:\test1>for /f "tokens=4 delims=\" %a in ('echo E:\test1\New Text Document (2).
txt') do set cust=%a
ASKER CERTIFIED SOLUTION
Avatar of SteveGTR
SteveGTR
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SteveGTR - u da man!
Thanks for all your help, script is running like a champ is flexible enough so that I can manipulate the date, source directory, and even the directory structure by changeing the token.

Great job!
Glad to help :)
Please let me know if I should post a new question for this...

This script is working great, but the file counts seem to be off.  Is there a way I can dump the file names it is counting to a log file so I can verify both the number of files and the actual files with the associated date that the script is using?  

This is the current version of the script I am using:

@echo off

setlocal
set srcDir=E:\Biztime\Scan\InDir\scan_dir\0_USARC
set dirMask=*.pdf

if not "%1"=="" set srcDir=%1

if not exist "%srcDir%" echo Directory %srcDir% does not exist.&goto :EOF

set freq=1

if not "%~2"=="" set freq=%~2

if "%freq%"=="" set /p freq=Enter number of days to run processing for:

if "%freq%"=="" echo Processing aborted&goto :EOF

call :GETDATEPARTS "%date%"
call :SUBTRACTDAYS %freq%

set cutoffDate=%yy%%mm%%dd%

set /a totalCnt=0

set outFile=%~0.out

pushd "%srcDir%"

if exist "%outFile%" del "%outFile%"

for /f "tokens=*" %%a in ('dir /b /a-d /S "%dirMask%"') do call :PROCESS "%%a" %%~ta

if not exist "%outFile%" echo Did not find any files to processing&goto CLEANUP

echo Total files updated in the last %freq% day(s): %totalCnt%

rem if exist "c:\temp\defc_totals_daily.txt" del /q "c:\temp\defc_totals_daily.txt"
echo Report for %date%. >> c:\temp\defc_totals_daily.txt
echo . >> c:\temp\defc_totals_daily.txt
echo Totals for %srcdir%. >> c:\temp\defc_totals_daily.txt
echo . >> c:\temp\defc_totals_daily.txt
echo Total files updated in the last %freq% day(s): %totalCnt%. >> c:\temp\defc_totals_daily.txt
echo . >> c:\temp\defc_totals_daily.txt
echo %totalCnt%>> c:\temp\defc_daily_usarc.txt

sort "%outFile%">"%~0.srt"

set lastKey=

set /a totalCnt=0

for /f "tokens=*" %%a in ('type "%~0.srt"') do call :TALLYCUST "%%a"

call :TALLYCUST

:CLEANUP

if exist "%outFile%" del "%outFile%"
if exist "%~0.srt" del "%~0.srt"

popd

goto :EOF

:TALLYCUST

if "%~1"=="%lastKey%" set /a totalCnt+=1&goto :EOF

if not "%lastKey%"=="" echo Total for %lastKey%: %totalCnt%

if not "%lastKey%"=="" echo Total for %lastKey%: %totalCnt%. >> c:\temp\defc_totals_daily.txt


set lastKey=%~1

set /a totalCnt=1

goto :EOF

:PROCESS

set cust=

REM Change token to 7 for team one and team 2, change token to 6 for NIH and USARC
for /f "tokens=6 delims=\" %%a in ('echo "%~1"') do set cust=%%a

if "%cust%"=="" goto :EOF

call :GETDATEPARTS %2

if /i "%cutoffDate%" GTR "%yy%%mm%%dd%" goto :EOF

echo %cust%>>"%outFile%"

set /a totalCnt+=1

goto :EOF

:GETDATEPARTS

set dt=%~1
set tok=1-3

if "%dt:~0,1%" GTR "9" set tok=2-4

set yyyy=

for /f "tokens=%tok% delims=.:/-, " %%a in ('echo %~1') do (
  for /f "skip=1 tokens=2-4 delims=/-,()." %%x in ('echo.^|date') do set %%x=%%a&set %%y=%%b&set %%z=%%c
)

if not "%yyyy%"=="" set yy=%yyyy%

if 1%yy% LSS 1000 (if %yy% LSS 70 (set yy=20%yy%) else (set yy=19%yy%))
if 1%mm% LSS 100 set mm=0%mm%
if 1%dd% LSS 100 set dd=0%dd%

goto :EOF

:SUBTRACTDAYS

set dayCnt=%~1

if "%dayCnt%"=="" set dayCnt=1

REM Substract your days here
set /A dd=1%dd% - 100 - %dayCnt%
set /A mm=1%mm% - 100

:CHKDAY

if /I %dd% GTR 0 goto DONESUBTRACT

set /A mm=%mm% - 1

if /I %mm% GTR 0 goto ADJUSTDAY

set /A mm=12
set /A yy=%yy% - 1

:ADJUSTDAY

if %mm%==1 goto SET31
if %mm%==2 goto LEAPCHK
if %mm%==3 goto SET31
if %mm%==4 goto SET30
if %mm%==5 goto SET31
if %mm%==6 goto SET30
if %mm%==7 goto SET31
if %mm%==8 goto SET31
if %mm%==9 goto SET30
if %mm%==10 goto SET31
if %mm%==11 goto SET30
REM ** Month 12 falls through

:SET31

set /A dd=31 + %dd%

goto CHKDAY

:SET30

set /A dd=30 + %dd%

goto CHKDAY

:LEAPCHK

set /A tt=%yy% %% 4

if not %tt%==0 goto SET28

set /A tt=%yy% %% 100

if not %tt%==0 goto SET29

set /A tt=%yy% %% 400

if %tt%==0 goto SET29

:SET28

set /A dd=28 + %dd%

goto CHKDAY

:SET29

set /A dd=29 + %dd%

goto CHKDAY

:DONESUBTRACT

if /I %mm% LSS 10 set mm=0%mm%
if /I %dd% LSS 10 set dd=0%dd%


goto :EOF

Remarking out the CLEANUP files might be helpful in debugging the processing:

:CLEANUP

REM if exist "%outFile%" del "%outFile%"
REM if exist "%~0.srt" del "%~0.srt"

Then look at the above files. Do this to see what they are:

dir /od

They should be listed last.
Thanks,  I tried that before posting, but it only produces the lastkey info which is a bunch of entries in the output file that look like "USARC_0".  It doesnt tell me filenames or give me any specific info.  I think it uses these entries to tally up how many files it found.

0_USARC
0_USARC
0_USARC
0_USARC
0_USARC
0_USARC
0_USARC
0_USARC
0_USARC
0_USARC
After this command:

pushd "%srcDir%"

Add this command:

if exist "debug.txt" del "debug.txt"

In the PROCESS routine you can decide whether to dump info before or after (or both) to the debug file. Here's an example when the file is selected:

:PROCESS

set cust=

REM Change token to 7 for team one and team 2, change token to 6 for NIH and USARC
for /f "tokens=6 delims=\" %%a in ('echo "%~1"') do set cust=%%a

if "%cust%"=="" goto :EOF

call :GETDATEPARTS %2

if /i "%cutoffDate%" GTR "%yy%%mm%%dd%" goto :EOF

echo File: %~1 Cust: %cust% Date: %yy%%mm%%dd% Cutoff: %cutoffDate% >>"debug.txt"

echo %cust%>>"%outFile%"

set /a totalCnt+=1

goto :EOF
man you are good..  Thank!
If nothing else I am a world class debugger :)
Hi,
I am looking for this script but my directory structure is as follows:
d:\pbx\ 4000
            4001
            4002
inside 4000\20071129
                   20071130
Same for all the other folders in pbx directory

I like to get output log file  in this manner :
d:\pbx\4000\20071130\  filename1
                                       filename2
 total new files for 4000\20071209 = 2

d:\pbx\4001\20071130\  filename1
                                       filename2
 total new files for 4001\20071209 = 2

I will be running the script on daily basis.

it would also be really nice to have the script ignor files of certain sizes for example I like to the script to be able to ignor file sizes less than 500kb.
Thank you

Open a new question.
done
ID: 23014758