# Bat file - Check for existing folder, if not present create it



## Eranu (Sep 2, 2009)

Hi TSG,

I have created the bat file below to copy the newest file in a folder and rename it with that days date, I am not sure if it is the most efficient way of doing it but with the limited knowledge I have it was the best I could do and it does exactly what I want it to....well up to a point. If anyone can suggest a less clumsy way of doing it I would welcome suggestions.

Further to the functionality of the existing bat file I would like to also check for the existence of the containing folder so that when a new month arrives I don't have to sit and create all the folders for that month.

To clarify - I have a number of reports created on a daily basis contained in a directory named for that month and year, September 09 for example. Within this folder are reports named "somereport 020909.xls".

Currently the bat file checks the directory for the newest file and copies it with today's date, however at the start of a new month I need to create a new directory and copy the newest .xls file into it renaming it as appropriate for that day.

I would like to update the .bat file so that it does the following -

- Sets variables for that days date. 
- Checks for the existence of that months folder 
- If folder not found creates it and copies the newest file from the previous months folder renaming the .xls file accordingly. 
- If folder is found the simply carry on and copy the latest file in the folder and renames it as it does currently.

This is what I have so far -


```
@echo off & setLocal enableDELAYedexpansion

SET dd=%date:~0,2%
SET mm=%date:~3,2%
SET yy=%date:~8,2%
SET ndate=%dd%%mm%%yy%

if %mm%==01 set Month=January
 
if %mm%==02 set Month=February
 
if %mm%==03 set Month=March
 
if %mm%==04 set Month=April
 
if %mm%==05 set Month=May
 
if %mm%==06 set Month=June
 
if %mm%==07 set Month=July
 
if %mm%==08 set Month=August
 
if %mm%==09 set Month=September
 
if %mm%==10 set Month=October
 
if %mm%==11 set Month=November
 
if %mm%==12 set Month=December

set currentmonth=%Month% %yy%

::Report 1
::
::

set folder="J:\Folder\Folder with Spaces\Folder with Spaces & Special Chars\Folder\Logs\Folder log 1\2009\"

for /f "tokens=* delims=" %%P in (%folder%) do (
    set src="%%P%currentmonth%"
    set dest="%%P%currentmonth%"
    
)

pushd !src!

for /f "tokens=* delims= " %%a in ('dir/b/a-d/o-d *.xls') do (
set latest=%%a
goto :OK
)

:OK
copy "!latest!" !dest!\"Boring REPORT "%ndate%".xls" > nul

::Report 2
::
::


set folder="J:\Folder\Folder with Spaces\Folder with Spaces & Special Chars\Folder\Logs\Folder log 2\2009\"

for /f "tokens=* delims=" %%P in (%folder%) do (
    set src="%%P%currentmonth%"
    set dest="%%P%currentmonth%"
    
)

pushd !src!

for /f "tokens=* delims= " %%a in ('dir/b/a-d/o-d *.xls') do (
set latest=%%a
goto :OK
)

:OK
copy "!latest!" !dest!\"Another LOG "%ndate%".xls" > nul

::Report 3
::
::

set folder="J:\Folder\Folder with Spaces\Folder with Spaces & Special Chars\Folder\Logs\Folder log 3\2009\"

for /f "tokens=* delims=" %%P in (%folder%) do (
    set src="%%P%currentmonth%"
    set dest="%%P%currentmonth%"
    
)

pushd !src!

for /f "tokens=* delims= " %%a in ('dir/b/a-d/o-d *.xls') do (
set latest=%%a
goto :OK
)

:OK
copy "!latest!" !dest!\"Captains LOG "%ndate%".xls" > nul


::Report 4
::
::

set folder="J:\Folder\Folder with Spaces\Folder with Spaces & Special Chars\Folder\Logs\Folder log 4\2009\"

for /f "tokens=* delims=" %%P in (%folder%) do (
    set src="%%P%currentmonth%"
    set dest="%%P%currentmonth%"
    
)

pushd !src!

for /f "tokens=* delims= " %%a in ('dir/b/a-d/o-d *.xls') do (
set latest=%%a
goto :OK
)

:OK
copy "!latest!" !dest!\"Minority Report "%ndate%".xls" > nul
```


----------



## Squashman (Apr 4, 2003)

I know just the man for the Job but he is usually on here late at night. TheOutCaste will probably be stopping by in about 14 hours and he will seriously tweak this Batch file. 

I can see you are doing some redundant steps. You should be able to take all those For Loops and combine then into 1 for loop and still have the same outcome. Basically each For loop will only run once because you are breaking out of it with a Goto statement. If there is more than one file in that directory it will never get copied. If there is only one file ever in that folder then you don't even need to use the goto statement. You can just remove the goto and it will drop into the copy statement regardless. You have a lot of redundant code.


----------



## TheOutcaste (Aug 8, 2007)

Squashman said:


> TheOutCaste will probably be stopping by in about 14 hours


13 1/2 hours, I think your precognition needs a little tweaking


Squashman said:


> Basically each For loop will only run once because you are breaking out of it with a Goto statement.


This is a good way to get the newest file in a folder that contains many files. By sorting "newest first" and jumping out after the first file you avoid processing a Set statement for each file in the folder. Slightly faster than using the default "oldest first" sort and just let the loop run though all the files.
This also lets you check if the folder is empty without having to clear the variable before each loop and then checking to see if it's Defined or not. If the folder is empty, the Goto will not be executed and it will fall through the loop, so if the loop completes you have no file found.
This version doesn't allow for that possibility and will just fall through use the last value for the *latest* variable which will likely cause an error as it will be either null for the first loop, or will have the name of the file from the previous log folder for the rest.

Shouldn't be too hard. Will definitely need some serious tweaking as you'll have to determine the previous months name as well as the year for the previous month so you can create the new and access the old.

A few questions:

 You say you have to manually create the *Month YY* folder. Does this mean you also have to manually change the path in the program that creates the reports?
If so, might be easier to let the program always create the reports in the same folder.
Then, *Move* the report to the appropriate *Year\Month YY* folder and then create the copy with the name you wish.
 Do you really want two copies of the report, one with the original name plus the renamed one?
 Does the program that creates the report make a new folder each year?
Again, if this has to be manually changed, easier to just always use the same folder, then move the reports to the dated folders each day.
This would also prevent you from copying yesterday's report and naming it with today's date if you happen to run the batch file before today's reports are created, as the folder will be empty.
 Does the path for each folder actually end with *Folder Log X\2009*
If so, can create one loop to go through all 4 folders instead of 4 nearly identical loops.
 You are using a space as the delimiter in the For loops with the DIR command. Is there a reason you specified a space?
If the file name starts with one or more spaces, they will be removed, and the file will not be renamed.
For example, if you have a report named *...New Report.xls* (pretend the periods are spaces), you'll get this:

```
latest=New Report.xls
instead of
latest=   New Report.xls
```
which will cause an error.
I'm assuming the folder structure looks something like this (showing just the tail end and a couple of folders for each year):

```
C:.
&#9500;&#9472;&#9472;&#9472;Folder Log 1
&#9474;   &#9500;&#9472;&#9472;&#9472;2008
&#9474;   &#9474;   &#9500;&#9472;&#9472;&#9472;December 08
&#9474;   &#9474;   &#9492;&#9472;&#9472;&#9472;November 08
&#9474;   &#9492;&#9472;&#9472;&#9472;2009
&#9474;       &#9500;&#9472;&#9472;&#9472;August 09
&#9474;       &#9492;&#9472;&#9472;&#9472;September 09
&#9500;&#9472;&#9472;&#9472;Folder Log 2
&#9474;   &#9500;&#9472;&#9472;&#9472;2008
&#9474;   &#9474;   &#9500;&#9472;&#9472;&#9472;December 08
&#9474;   &#9474;   &#9492;&#9472;&#9472;&#9472;November 08
&#9474;   &#9492;&#9472;&#9472;&#9472;2009
&#9474;       &#9500;&#9472;&#9472;&#9472;August 09
&#9474;       &#9492;&#9472;&#9472;&#9472;September 09
&#9492;&#9472;&#9472;&#9472;Folder Log 3
    &#9500;&#9472;&#9472;&#9472;2008
    &#9474;   &#9500;&#9472;&#9472;&#9472;December 08
    &#9474;   &#9492;&#9472;&#9472;&#9472;November 08
    &#9492;&#9472;&#9472;&#9472;2009
        &#9500;&#9472;&#9472;&#9472;August 09
        &#9492;&#9472;&#9472;&#9472;September 09
```
I would let the report generator create the reports in the *Folder Log X* folder, then have the batch file move it to the *2009\September 09* subfolder, then create a copy and rename it with today's date.

So other observations:
You've used the *:OK* label in 4 different places. While this works for labels that come after the Goto, it's good practice to use unique labels to avoid confusion. And if the specified label is not found after a Goto, it will start searching from the start of the file, and jump back to the first one, which can cause unexpected results.
Plus, never can tell when that "feature" will be removed, and unique label names will be required.

It's also good practice to use a *PopD* statement for each *PushD*. When the batch file ends, it does not clear the stack used to store the current path so it will use a little memory, and you'll also be in the last folder you switched to, instead of the one you started from. Not a big problem as this is cleared when the Command Prompt closes, but if you are using UNC paths you can quickly run out of drive letters, as *PushD* maps UNC paths to Drive letters, and these are *not* released when the Command Prompt closes. They will not be removed by a reboot either, unless you've changed the Net Use setting to be *not persistant*


----------

