[J3 Computer Technologies - http://www.os2store.com/]

[Previous]
the Rexx Files- by Dr. Dirk Terrell
 [Next]

This month on the OS2USER mailing list someone asked about a Rexx program that would run a command multiple times on a list of files matching a wildcard. The specific request was addressed to using Info-Zip's "-o" option which changes the date and timestamps on a zip file to match the date of the zip match those of the latest entry in the zip file. For example,

zip -o backup.zip
would make the file backup.zip have the date and time of the newest file in the zip file.

Unfortunately, if you have many zip files you wish to change, you cannot use

zip -o *.zip
because Info-Zip doesn't support wildcards for the archive name. This is a situation where a Rexx script will work nicely. Using the REXXUTIL library, you can get a list of files matching the wildcard, then execute Info-Zip on each file. Let's write a program called REPEAT.CMD that will perform this function for a specified program.

The calling form of the program will be

repeat command pre_options wildcard post_options
where command is the command we want to execute multiple times, pre_options and post_options are the command line options for the command that come before and after the wildcard respectively, and wildcard is the wildcard specification for the list of files we want to process. Basically, all we have to do is make the command line that we would like to run be the input to the program. For example, with the Info-Zip scenario above, it would be
repeat zip -o *.zip
where, in this case post_options is blank.

To process the input, we have to find the word that has the wildcard (the asterisk) and then look on each side to get the pre and post options. Finding the wildcard is easy. We use the POS function on each blank-delimited word in the input. (I should say that we will assume that the first appearance of the asterisk is the wildcard.) To loop through the words, we use the WORDS function to get the number of words, and then set up a DO loop to check each word using the WORD function to get each word. The calling form for the WORD function is

WORD(String,i)
where String is the string we are working on, and i is the index of the word we want, with 1 being the first word, 2 being the second, and so on. Here is the loop that finds which word in the string contains the wildcard:
/* Find the word that has the wildcard */
NWords=Words(Commandline)
Do i=1 to NWords
   If Pos("*",Word(Commandline,i))<>0 then Do
      WildcardIndex=i
      Leave
   end /* do */
end /* do */
We store the index of the word that contains the wildcard and exit the do loop with the LEAVE command when we find the wildcard.

Next we get the pre and post options as well as the wildcard itself by looping over all the words again. (This could be done in the loop where we searched for the wildcard, but for the sake of clarity, I have chosen to use two separate loops.) All of the words up to (but not including) the word containing the wildcard should be stored as the pre options and those after the wildcard word should be stored as the post options. We'll just initialize two variables as null (blank) strings and then append words to them as we go through the loop. Here is the code to do this:

/* Set up the command line for the external command.  We need the 
   stuff before the wildcard and the stuff after it to prepend
   and append to the files that the wildcard search will produce.
*/
CommandPre=""
CommandPost=""
Do i=1 to NWords
   Select
      when i<WildcardIndex then
         CommandPre=CommandPre Word(Commandline,i) /* Will include the command itself */
      when i>WildcardIndex then
         CommandPost=CommandPost Word(Commandline,i)
   otherwise
      Wildcard=Word(Commandline,i) /* This word is the wildcard */
   end  /* select */
end /* do */
Now we need to get the list of files that match the wildcard. With the SysFileTree function in the REXXUTIL library, this is a trivial matter. The calling form is
rc=SysFileTree(wildcard,results_stem,options)
where wildcard is the pattern to match, results_stem is a Rexx stem variable that will hold the list of matching files, and options are the options to use; of which we will use "FO" which means we want only filenames (no dates, times or file sizes) and only files (no directories) that match the search pattern. See the Rexx online documentation for the other options. Our call will look like this:
/* Now find the files that match the wildcard and execute 
   the external program.  First load the REXXUTIL library.
*/
call rxfuncadd 'SysLoadFuncs','RexxUtil','SysLoadFuncs'
call sysloadfuncs

/* Now get the list of files matching the wildcard spec */
rc=SysFileTree(WildCard,"File.","FO")
Finally, we need to loop over all of the files that matched the wildcard and execute the command. In the loop we will form a string that concatenates the pre options, the filename, and the post options. Then we will pass the string to the system for execution. It is possible that no files will match the wildcard, and of course there is nothing for the external program to do. The 0 index of the results stem will contain the number of files that match the wildcard. If it is 0, then we print a message to the user that no matches were found, otherwise we loop that many times, calling the external program. Here is the final bit of code that accomplishes this:
/* Loop over the list of files and run the external program */
If File.0=0 then Do
   Say " " 
   Say "No files matching the wildcard were found."
   End
Else Do
   Do i=1 to File.0
      Command=CommandPre File.i CommandPost /* Form the command */
      Command  /* Execute the command */
   end /* do */
End
This little program should work for any command that only has a single word with asterisks in it. Commands with multiple words containing asterisks (e.g. foo -u *.zip *.gif) require a little more work if the REXX program is supposed to use the wildcards after the first one. A modification that wouldn't be too difficult would be to add support for the "?" wildcard (match any letter in that position). This month's sample code contains the full REPEAT.CMD program.

* * *

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.


 [ Previous]
[Index]
 [Feedback]
 [Next ]

[Our Sponsor: Keller Group Inc. - Developers of FaxWorks for OS/2 and PMfax.]

Copyright © 1997 - Falcon Networking ISSN 1203-5696