From shf@well.sf.ca.us  Ukn Aug  1 01:14:30 1993
Received: from bobsbox.rent.com by rutgers.edu (5.59/SMI4.0/RU1.5/3.08) with UUCP 
	id AA10001; Sun, 1 Aug 93 01:42:44 EDT
Received: by bobsbox.rent.com (V1.16/Amiga)
	id AA02lya; Sun, 1 Aug 93 01:26:23 EDT
Received: from nkosi.well.sf.ca.us by rutgers.edu (5.59/SMI4.0/RU1.5/3.08) 
	id AA04395; Sun, 1 Aug 93 01:10:33 EDT
Received: from well.sf.ca.us (well.sf.ca.us [192.132.30.2]) by nkosi.well.sf.ca.us (8.5/8.5) with SMTP id WAA16226; Sat, 31 Jul 1993 22:10:30 -0700
Received: by well.sf.ca.us id <13989-1>; Sat, 31 Jul 1993 22:10:09 -0700
Message-Id: <93Jul31.221009pdt.13989-1@well.sf.ca.us>
Date: 	Sat, 31 Jul 1993 22:10:05 -0700
From: "Stuart H. Ferguson" <shf@well.sf.ca.us>
To: lightwave@bobsbox.rent.com
Subject: Useful ARexx Script for Sequences
Status: RO
X-Status: 

If you find yourself manipulating image sequences as much as I do, you
may find this little ARexx script useful.  It is used as a shell command
preprocessor and allows any shell command to be invoked iteratively on
a series of images.  This makes it easy to do things like:

	Delete images MyFG001 through MyFG030 ...
	cli> seq delete MyFG#30#

	Delete every other image from Imgs001 - Imgs020 ...
	cli> seq delete Imgs#2,20,2#

	Rename the remaining images as NewSeq001 - NewSeq010 ...
	cli> seq rename Imgs#1,20,2# NewSeq#

Have fun ...

		Stuart Ferguson		(shf@well.sf.ca.us)
			Prepare to Surge to Sublight Speed!
----------------

/*
 * SEQ -- Command Sequence Processor
 *
 * This takes a shell command with special pattern codes embedded in it
 * and issues a sequence of shell commands generated by filling in the
 * patterns.  This allows for one-line processing of a sequence of files
 * such as LightWave image sequences.
 *
 * Some examples:
 *
 *	CLI> seq copy abc#30# abc#.bku
 *	copy abc001 abc001.bku
 *	copy abc002 abc002.bku
 *	 ...
 *	copy abc030 abc030.bku
 *
 *	CLI> seq rename img#1,20,2# ximg#3,10#
 *	rename img001 ximg003
 *	rename img003 ximg004
 *	rename img005 ximg005
 *	 ...
 *	rename img017 ximg011
 *	rename img019 ximg012
 *
 * It takes the command line and breaks it up into words.  Each word
 * can contain a sequence pattern which will be expanded into a sequence
 * of words with numbers replacing the pattern code.  The codes can be
 * in the following forms:
 *
 *      pattern form          start    end     step
 *      ------------          -----    ---     ----
 *	 #			1	1	1
 *	 #N#			1	N	1
 *	 #K,N#			K	N	1
 *	 #K,N,S#		K	N	S
 *
 * Any word without a pattern is just a constant which gets repeated
 * in each iteration.  The total number of iterations for the combined
 * command is the MAXIMUM number of elements in any sequence.
 *
 * If the command line is preceded by a hyphen (i.e. "seq -copy ..."),
 * the commands will be generated and displayed but not envoked as
 * shell commands.  This allows you to test a complex pattern before
 * letting it work on real files.
 *
 * This should be placed in the "S:" directory and have its script bit
 * set to work as indicated in the above examples.
 *
 * 7/93		Stuart Ferguson
 */


call addlib("rexxsupport.library",0,-30,0)

/* Get command line from shell.
 */
parse arg cmdline

/* Look for leading hyphen to see if this is a real command.
 */
forreal = 1
cmdline = strip(cmdline)
if (left(cmdline, 1) = '-') then do
    forreal = 0
    cmdline = strip(substr(cmdline,2))
end

/* Get number of words on command line.
 */
narg = words(cmdline)
if (narg < 1) then exit 10

/* Convert each word into sequence form and get the max sequence size
 * as the number of iterations.
 */
iter = 1
do i=1 to narg
    templ.i = namebreak(word(cmdline,i))
    iter = max(iter, namecount(templ.i))
end i

/* Generate a new command line by expanding each sequence pattern into
 * a specific instance for each iteration.
 */
do k=1 to iter
    cmd = ""
    do i=1 to narg
	cmd = cmd || iname(k,templ.i) || ' '
    end i

    say cmd
    if (forreal) then address command cmd
end k

exit



/*
 * NameBreak converts a pattern word into a sequence descriptor.  The
 * descriptor consists of five words: name pattern, number of digits,
 * start index, step, end index.  Pattern is a word with a '*' in it
 * where the number will go.
 */
NAMEBREAK: procedure
    parse arg name

    /* Find first pattern marker.  If none, this is a constant sequence.
     */
    p1 = pos('#',name)
    if (p1 = 0) then return name || "* 0 1 1 1"

    /* Find second pattern marker, if any.
     */
    p2 = pos('#',name,p1+1)
    if (p2 = 0) then p2 = p1

    /* Split out head and tail sections.  If no second pattern marker,
     * just set defaults.
     */
    head = substr(name,1,p1-1)
    tail = substr(name,p2+1)
    pat = head || "*" || tail
    if (p1 = p2) then return pat 3 1 1 1

    /* Parse sequence numbers.  Step defaults to 1.  Start defaults to 1.
     */
    larg = substr(name,p1+1,p2-p1-1)
    parse var larg n0 ',' n1 ',' step
    if (step = "") then step = 1
    if (n1 = "") then do
	n1 = n0
	n0 = 1
    end

    return pat 3 n0 step n1


/*
 * NameCount takes a sequence descriptor and returns the number of elements
 * defined by the sequence.
 */
NAMECOUNT: procedure
    arg pat ndig n0 step n1 .
    return (n1 - n0 + step) % step


/*
 * IName takes an index and sequence descriptor and returns the name 
 * generated for the given index.
 */
INAME: procedure
    parse arg i, pat ndig n0 step .
    parse var pat head '*' tail
    num = right(n0 + step * (i - 1), ndig, 0)
    return head || num || tail

----------------- end --------------


