I would like to have a script that can copy data to a different folder each day of a 7-day cycle via a scheduled task. The script should reuse the same set of seven folders each week and should send its results to a log file. Can this be done?
When I encounter a question about a script copying files, I usually think of Robocopy, a powerful utility that Microsoft provides as a part of the Windows resource kit tools download. (For more information about Robocopy, see "Robocopy FAQ," July 2003, InstantDoc ID 39119.) Robocopy has lots of options that provide precise control over copying operations. It also provides a logging feature. However, performing the copying
based on the day of the week is where scripting comes into play.
Determining the day of the week. An important aspect of such a script is that it needs to be able to determine the day of the week. In US English versions of Windows 2000 and later, the first three characters of the DATE environment variable should contain the day of the week. A script I wrote that echoes the current day of the week, dow.cmd, is shown in Listing 1. Dow.cmd uses cmd.exe's variable substring feature to extract the first three characters of the DATE environment variable and echoes the result. To see details about how variable substrings work, type the command
at a command prompt.
However, dow.cmd might fail if you have other date format or localization settings. Because of this, I wrote a short command-line program, dow.exe, that does the same thing but works regardless of the date format or localization settings. (Dow.exe and its source code, along with the code in the listings in this article, are available for download at http://www.windowsitpro.com/windowsscripting.)
To determine whether dow.cmd will work in your environment, simply run it from a command prompt. If it doesn't correctly echo the three-letter abbreviation for the current day of the week, you can use dow.exe instead.
Understanding dowcopy.cmd. I wrote a shell script, dowcopy.cmd, that uses dow.cmd (or dow.exe) to determine the current day of the week, then uses Robocopy to copy files from a list of source folders to a target folder. The script uses Robocopy's logging capability to record its activity to a log file in a specified folder. Dowcopy.cmd, shown in Listing 2, uses the following command-line syntax:
Dowcopy foldermapfile folderlistfile logfolder
If any filename or folder name specified in one of the three parameters contains spaces, the name must be enclosed in quotes.
Foldermapfile is a text file that should contain seven lines (one for each day of the week). The first word on each line should be the three-letter abbreviation for the day of the week as returned by dow.cmd or dow.exe. After the abbreviation on each line, enter a space followed by the target folder that the script should use for that day. Don't enclose the target folder in quotes if it contains spaces. Figure 1 shows a sample folder mapping file; using this mapping file would mean that on Tuesday, the target folder is \\SERVER2\Backup Files\3-Tuesday. This example assumes that the server SERVER2 has a share called Backup Files, that the 1-Sunday through 7-Saturday folders exist in that share, and that the account that will run the script has write privileges on the share and the folders.
Folderlistfile is a text file that contains a list of source folders holding the files you want to copy. Each source folder name should be listed on a separate line and shouldn't be enclosed in quotes if it contains spaces. The folder names must not end with a backslash (\). Figure 2 shows a sample folder list file.
Logfolder is the folder in which the log file should be written. The script uses Robocopy's logging feature to create a separate log file for each day of the week. The log file will be named for the day of the week and appended with .log (e.g., Fri.log on Friday). Note that you'll need to create the log folder before running the script. The log files will be overwritten weekly.
For example, suppose you want to copy the folders listed in the FolderList.txt file to the directories listed in the FolderMap.txt file and you want to write the log files to the C:\Logfiles folder. You would use the following command:
Dowcopy FolderMap.txt FolderList.txt C:\Logfiles
When specifying a folder on a remote computer for either the folder mapping or folder list files use Universal Naming Convention (UNC) paths rather than mapped drives. Mapped drives are a per-user setting; they might be different depending on which account is running the script and thus can cause failures or unexpected results.
Dowcopy.cmd works by first verifying that it has at least three command-line parameters. Next, it verifies the existence of the folder mapping and folder list files as well as the log file folder. If these checks fail, the script aborts with an error message and a nonzero exit code. After these initial checks, the script runs dow.cmd (or dow.exe) to retrieve the abbreviation for the day of the week into the variable DOW, which callout A in Listing 2 shows. The DOW variable is used to determine the target folder for the current day as well as the log file name.
Next, the script uses the For command to parse the folder mapping file, as callout B shows. If the first token on each line of the mapping file matches the day-of-week abbreviation stored in the DOW variable, the script sets the TARGET variable to the target folder name for that day. If this action fails or if the target folder doesn't exist, the script aborts with an error message and a nonzero exit code.
After deleting the daily log file, the script reads each line in the folder list file and passes it as the source folder to the PROCESS procedure, which I'll describe in a moment. After all the folders have been processed, the RC variable contains the highest exit code the PROCESS procedure returned. This value is the script's exit code.
Inside the PROCESS subroutine. The script uses the PROCESS subroutine to perform the file copying. At this point, the script knows the source and target folder names. The next step is to create a subfolder inside the target folder that matches the source folder's name if the subfolder doesn't already exist. Otherwise, files from all the source folders will be written to the same target folder. For example, if the source folder is C:\Inetpub\www-root and the target folder is D:\Backup-Wed, you want the files and folders in the wwwroot folder to be copied directly into D:\Backup-Wed\wwwroot, not into D:\Backup-Wed. If you imagine that multiple source folders are in the folder list file, you can see why it's important to create a separate subfolder in the target folder for each source folder.
To address this requirement, the PROCESS subroutine uses the For command to extract the ending folder name from the source folder, then appends it to the target folder's name, as shown in callout C. For example, if the source folder is C:\Inetpub\ftproot and the target folder is D:\Backups\5-Thursday, the new target folder would be D:\Backups\5-Thursday\ftproot.
The PROCESS procedure then executes Robocopy to copy the files. You can customize the script's file-copying behavior by modifying the Robocopy command's options to meet your requirements. The procedure's return value will be equal to Robocopy's exit code, which will be nonzero if an error occurred.
Scheduling the script. To schedule dowcopy.cmd, copy it and dow.cmd (or dow.exe) to a folder of your choice. If you don't have the resource kit tools package installed, put a copy of robocopy.exe in this folder as well. Next, create the folder mapping and folder list files in the same folder. Make sure the Start in folder for the scheduled task is set to this folder also. Finally, make sure that the account you're using to execute the scheduled task has sufficient permissions to access the files and folders you intend to copy.