[Products and Resources for VisualAge (click here).] [BMT Micro - Registration site for the best OS/2 shareware applications available. (click here).]

Rexx Files- by Dr. Dirk Terrell

Summary: Dirk shows how to write a program that automatically archives a list of files and directories while paying attention to what filenames are valid on different file systems.

This month a reader asked me about a Rexx program that could archive a specified set of directories with Info-Zip and give the zip file a name that indicated the date that the archive was made. So, let's put a Rexx program together that does this.

First let's deal with creating a name for the zip file that indicates the date it was archived. The DATE() function returns the current date in a variety of formats depending on the string you pass to it. Below is the list of examples from the online Rexx documentation that comes with OS/2:

DATE( )        ->    '27 Aug 1988'  /*  perhaps  */
DATE('B')      ->    725975
DATE('D')      ->    240
DATE('E')      ->    '27/08/88'
DATE('L')      ->    '27 August 1988'
DATE('M')      ->    'August'
DATE('N')      ->    '27 Aug 1988'
DATE('O')      ->    '88/08/27'
DATE('S')      ->    '19880827'
DATE('U')      ->    '08/27/88'
DATE('W')      ->    'Saturday'
Now, we have to be careful about filenames if we are writing to a FAT drive instead of an HPFS drive because of the 8.3 filename limitation. Let's make our program smart enough to detect which type of file system we have. If the file system is HPFS, let's make the filename of the form
and for FAT:
We could make the HPFS version use names like 1988_August_27.zip, but that would mess up sorting in directory listings. So, we will call the DATE() function with the "S" parameter. Then we will pull the year, month and day out of it like this:
DateString = Date("S")
Year = SubStr(DateString,1,4)
Month = SubStr(DateString,5,2)
Day = SubStr(DateString,7,2)
and then create the HPFS filename using concatenation:
FileName = Year||"_"||Month||"_"||Day||".zip"
Next we must check to see what type of file system we have. We can do this by trying to open a file with a filename that violates the 8.3 convention. If successful, then we know we can use long filenames. If it fails, then we will have to use a filename that fits the 8.3 format. We can use the STREAM() function to open the file:
rc=Stream(FileName,"C", "Open")
and then check the return value (stored in variable rc above) to see if it was successful. Variable rc will contain "READY" if successful and something else if the open command failed. So, we test rc and if the open command failed, we create a legal filename:
If Pos("READY",rc)=0 then
To avoid problems with Info-Zip, we need to close the file after performing the test and delete it. So the section of code for getting the filename right should look like this:
/* Create a name for the zip file, FAT-compatible if necessary */
FileName = Year||"_"||Month||"_"||Day||".zip"
rc = Stream(FileName,"C", "Open")  /* Can we create this file? */
rc2 = Stream(FileName,"C","Close") /* Close the file */
/* Register REXXLIB functions and then delete the file */
call rxfuncadd 'SysLoadFuncs','RexxUtil','SysLoadFuncs'
call sysloadfuncs
rc2 = SysFileDelete(FileName)      /* Delete it so we don't mess up Info-Zip */

If Pos("READY",rc)=0 then
   FileName = DateString||".zip"
Granted, this isn't the most elegant method to deal with determining file system type, but it works. At this point we have a valid name for our zip file no matter which file system we're on.

Now we need to interface with Info-Zip to do the archiving. (I'll assume we have Info-Zip properly installed.) We need to know what Info-Zip is supposed to archive. Let's give ourselves some flexibility and read the files from a text file that lists the things to archive. The format of this text file will be just a listing of files on one or more lines, with wildcards allowed. For example, let's say that we want archive all of the files in D:\DEV\PROJECTS\ and the C:\CONFIG.SYS file. Our text file would look like this:

For now, let's assume that the * wildcard means all files in the stated directory and all files in its subdirectories, so that D:\DEV\PROJECTS\* would include all the files in D:\DEV\PROJECTS\JAVA\ for example. We now read the file one line at a time and execute Info-Zip for each one:
Do While Lines(SourceFile)
   Source = Linein(SourceFile)
   "zip -r" FileName Source      /* Execute Info-Zip, -r makes it recursive through sub-dirs. */
where SourceFile holds the name of the text file with the list of files to be processed. We will pass that to the program as a command line parameter and retrieve it at the beginning of our program:
Parse Arg SourceFile
At this point we have a functional program. There are some things that could be added, such as the ability to specify whether the '*' wildcard should be recursive through subdirectories (perhaps use '*' for non-recursive and '**' for recursive), or the ability to automatically FTP the zip file to another site as a backup (see the Rexx Files column in the September 1996 issue for details), but this gives you a good start. You could combine this program with a scheduling program like cron (ZIP,135K) and have this program run automatically everyday to back up important files.

Download the source code for this month's Rexx Files.

* * *

Dr. Dirk Terrell is an astronomer at the University of Florida specializing in interacting binary stars. His hobbies include cave diving, martial arts, painting and writing OS/2 software such as HTML Wizard.

Copyright © 1998 - Falcon Networking ISSN 1203-5696