Monday, March 21, 2011

Copy file created within 1 day, rename it & log results, using forfiles

As it turns out forfiles has once again found itself as the solution to yet another situation since my recent post on it. This time around the objective was slightly different and I’m going to share it as a continuation on the possible uses of the forfiles exe.

The overview of the situation and objective was this:

  • Files are written to a directory by an application. One of these files needs to be uploaded to another location each day but first it needs to be copied to another folder and renamed.

  • There is a copy of this file in the directory from every day of the week, so I have to ensure the file being copied is the one most recently created.

  • The file needs to be copied to another folder on another server as mentioned

  • The file needs to be renamed in the format yearmonthdate_file.bak

      • The yearmonthdate listed needs to be that of when the file was created/modified.

  • Needed a way to review the results of the process for future reference and or troubleshooting.

Below is what I ended up with:

@echo off & setlocal enableextensions

net use m: "\\server\path"

echo %date:~-10,10% %time:~-11,5% >> m:\script.log
echo. >> m:\script.log

forfiles –pC:\folder\parsing\files\from -d+1 -m*.bak -c"CMD /C copy @FILE  m:\@FDATE_file.bak & echo Source File: @PATH\@FILE & echo Destination File m:\@FDATE_file.bak" >> m:\script.log

echo. >> m:\script.log
echo. >> m:\script.log
echo. >> m:\script.log

net use /delete m:

Next let me break down the script for you as I often try to do:

net use commands map a temporary network drive for the purpose of copying the file to this location after which the mapped drive is removed.

net use m: "\\server\path"
net use /delete m:

Write the date and time the file is run to the log file

echo %date:~-10,10% %time:~-11,5% >> m:\script.log

The echo. is simply  used to add returns in the log file, strictly for formatting purposes

echo. >> m:\script.log

Lastly the important part of all this the forfiles command. There are infinite variations and uses for this command, mine is but of one example that may help you along.       (*Please see end about forfiles version*)

forfiles –pC:\folder\parsing\files\from -d+1 -m*.bak -c"CMD /C copy @FILE  m:\@FDATE_file.bak & echo Source File: @PATH\@FILE & echo Destination File m:\@FDATE_file.bak" >> m:\script.log

            Sets the path from which you want to parse\copy\etc files from

                        –pC:\folder\parsing\files\from

Says to check for files matching current date or 1 day from today’s date, see help for more detail

-d+1

Expression you want to match on, below says all files with .bak extension

-m*.bak

This is the command you want to run against the file(s) which are parsed from the above match statement. See end for listing of variables and explanation.

-c"CMD /C copy @FILE  m:\@FDATE_file.bak


These commands are for the purpose of the log file, the first writes the path and name of the file being copied and the second is the renamed file and path it was copied too.

& echo Source File: @PATH\@FILE
& echo Destination File m:\@FDATE_file.bak"

This writes the result to the log file, either 1 file copied or 0 files copied

>> m:\script.log

Put it all together, create a scheduled task and you get a smooth process with a nice log file.

Something of important note when using forfiles, check to see which version you have on your computer. An easy way to tell is to look at the help.

For example: if you type forfiles /? and get an output of the help with / ? windows style command switches then you have the newer version. If however this doesn’t return the help output you likely have the older version. Typing simply forfiles in this other version would return the help output which uses –p  *nix style switches. Either version should work fine as you can see I’ve written the above using the older style commands but it could be easily adapted to work with the newer version as well. The help output for both will be listed below.

-----------------------------------------------------------------------

Syntax
      FORFILES [/p Path] [/m Mask] [/s] [/c Command] [/d [+ | -] {dd/MM/yyyy | dd}]  

Key
   /p Path      The Path to search  (default=current folder)

   /s           Recurse into sub-folders

   /C command   The command to execute for each file.
                Wrap the command string in double quotes.
                Default = "cmd /c echo @file"

The Command variables listed below can also be used in the command string.

   /D date     Select files with a last modified date greater than or
equal to (+), or less than or equal to (-),the specified date using the "dd/MM/yyyy" format; or selects files with a last modified date greater than or equal to (+) the current date plus "dd" days, or less than or equal to (-) the current date minus  "dd" days.

            A valid "dd" number of days can be any number in
the range of 0 - 32768. "+" is taken as default sign if not specified.

   Command Variables:
      @file    The name of the file.
      @fname   The file name without extension.                
      @ext     Only the extension of the file.                 
      @path    Full path of the file.
      @relpath Relative path of the file.         
      @isdir   Returns "TRUE" if a file type is a directory,
               and "FALSE" for files.
      @fsize   Size of the file in bytes.
      @fdate   Last modified date of the file.
      @ftime   Last modified time of the file.

-----------------------------------------------------------------------

Syntax : FORFILES [-pPath] [-mSearch Mask] [-ccommand]
[-d<+|-><DDMMYYYY|DD>] [-s]

-pPath Path where to start searching
-mSearch Mask Search files according to <Search Mask>
-cCommand Command to execute on each file(s)
-d<+|-><DDMMYYYY|DD> Select files with date >= or <=DDMMYYYY (UTC)
or files having date >= or <= (current date - DD days)
-s Recurse directories
-v Verbose mode

The following variables can be used in Command :
@FILE, @FNAME_WITHOUT_EXT, @EXT, @PATH, @RELPATH, @ISDIR, @FSIZE, @FDATE, @FTIME

-----------------------------------------------------------------------

Extras:

1: Change the output format of the %date% variable

If you echo %date% you will get something that looks like this: mon 3/21/2011

But lets say you want to use the current date in a file name with the help of this variable, how would you do this? The commands below will help you do just that.

Use the commands listed here:

FOR %%A IN (%Date%) DO (
    FOR /F "tokens=1-3 delims=/-" %%B in ("%%~A") DO (
        SET Today=%%D%%B%%C
    )
)

This creates variable %today% which changes the output of the date variable to look like this: 20110321. This is now an acceptable format for use in a filename or any other use you may have

2. Now what if you need the date but not of today, lets say you need yesterdays date or the date from 30 days ago, so on, the script below is just what you’re looking for. As is below, this code will output yesterdays date, today’s date -1. Changing the -1 would allow you to change the number of days back for which you want to display the date.

@echo off & setlocal enableextensions
set vbs_=%temp%\tmp$$$.vbs
>"%vbs_%" echo WScript.Echo DateAdd("d",-1,Date)
for /f "tokens=* delims=" %%a in (
'cscript //nologo "%vbs_%"') do set yd_=%%a
for %%f in ("%vbs_%") do if exist %%f del %%f

echo yd_=%yd_%

Above code from http://www.netikka.net/tsneti/info/tscmd006.htm

Hope you enjoyed the post and hope this helps you guys along!


No comments:

Post a Comment