home *** CD-ROM | disk | FTP | other *** search
/ Audio 4.94 - Over 11,000 Files / audio-11000.iso / msdos / sndbords / proaudio / fddmairq / fe.doc < prev    next >
Text File  |  1992-07-07  |  18KB  |  593 lines

  1. fe - copyright SHARK, 1991.
  2.  
  3. FOREACH - Command List Processor with Member Substitution and Modification
  4.  
  5. Programmer Bart Crane
  6.  
  7. Syntax
  8.     fe [-deq] [var] -llistfile    commandfile arg1 ...
  9.     fe [-deq] [var] ( member ... )    do command [; ...]
  10.  
  11. fe processes a list of commands on each of a number of words,
  12. substituting each into the $-prefixed embedded variable "var", 
  13. while performing certain modifications to this word.  fe also
  14. searches the environment for embedded DOS variables and can 
  15. use the DOS branching facilities "if ...", "goto" and labels.
  16.  
  17. Options
  18.     -d    debug, no execution, display processed command line
  19.     -e    echo, display command line during execution
  20.     -q    quiet, no prompting question mark
  21.  
  22. Members 
  23.  
  24. fe has two methods of specifying the list of words to be substituted
  25. into the command line:
  26.  
  27.     ( member ... )
  28.  
  29.         this indicates that each "member" between the
  30.         parentheses makes up the list, with members 
  31.         separated by whitespace.
  32.  
  33.     -l listfile
  34.  
  35.         "listfile" is the name of a file containing members.
  36.         if list is "-", then the standard input is read. 
  37.         No space is required between -l and its argument.
  38.         Members are separated by newlines.
  39.  
  40.  
  41. fe also will expand a pattern to a range of members:
  42.  
  43.     [0-9]    expands to 0 1 2 3 4 5 6 7 8 9 
  44.     [a-z]    expands to a b c ... x y z
  45.     [A-Z]    expands to A B C ... X Y Z
  46.  
  47.     "subranges" of each range are possible:
  48.  
  49.     [4-6]    expands to 4 5 6
  50.     [c-q]    expands to c d e ... o p q
  51.  
  52.     The range can comprise of a string:
  53.  
  54.     [000-999] expands to 001 002 003 ... 997 998 999
  55.     [aaa-zzz] expands to aaa aab aac ... zzx zzy zzz
  56.     [AAA-ZZZ] expands to AAA AAB AAC ... ZZX ZZY ZZZ
  57.  
  58.     and subranges of these strings are available, except
  59.     that aaa-fff expands to aaa aab ... aaz aba ... ffe fff.
  60.  
  61. Variables
  62.  
  63. fe accepts a string to act as the variable in the command line.
  64. In order to access the variable to allow substitution, preface
  65. the string in the command line with a dollar sign ($).
  66.  
  67.     var    "var" specifies a string (usually short: i)
  68.         searched for in the command line;  when found
  69.         following a "$", the current word in the
  70.         list is substituted:
  71.  
  72.         $var     = current word from list
  73.  
  74.     a missing "var" specifies "i":
  75.  
  76.         $i    = current word from list
  77.  
  78.     fe modifies the word to be substituted in order to 
  79.     make possible complex file-management commands by 
  80.     simply appending a string to the variable in the 
  81.     command line:
  82.  
  83.     Assume:    i =     d:\sub\dir\filename.ext
  84.  
  85.     $i:t    :t =    filename.ext        leave lowest path element
  86.     $i:h    :h =     d:\sub\dir        remove lowest path element
  87.     $i:e    :e =     ext            leave extension
  88.     $i:r    :r =    d:\sub\dir\filename    remove extension
  89.     $i:d    :d =    d:            leave only the drive designator
  90.     $i:s    :s =    \sub\dir\filename.ext    remove the drive designator
  91.     $i:f    :f =     filename.ext        leave the filename element
  92.     $i:p    :p =     d:\sub\dir        leave the pathname element
  93.  
  94.     (:f and :p are not implemented prior to version 4)
  95.  
  96.     Also, the numbers 1 through 9 cause only upto that number of
  97.     characters of the variable to be left:
  98.  
  99.     $i:1    :1 =     d            leave one character 
  100.     $i:2    :2 =     d:            leave two characters
  101.     ...
  102.     $i:9    :9 =    d:\sub\di        leave nine characters
  103.  
  104.     Note that modifiers can be concatenated and strings emebedded:
  105.  
  106.     $i:h:t    :h =     d:\sub\dir        remove lowest path element
  107.         :t =     dir            then leave lowest path element
  108.  
  109.     a:$i:t:r.$i:e:20
  110.            =    a:            embed "a:"
  111.         :t =     a:filename.ext        leave lowest path element
  112.         :r =     a:filename        remove extension
  113.            =     a:filename.        embed "."
  114.         :e =     a:filename.ext        append extension
  115.         :2 =     a:filename.ex        leave 2 chars of extension
  116.            =    a:filename.ex0        embed "0"
  117.  
  118.     Assuming i = d:\dir\sub\filename.ext
  119.  
  120.         copy $i a:$i:s:r:70.$i:e
  121.  
  122.             will expand to
  123.  
  124.         copy d:\dir\sub\filename.ext a:\dir\sub\filenam0.ext
  125.  
  126.     Assuming i = d:\dir\sub\filename.ext
  127.  
  128.         echo $i:d $i:s:h $i:t:r $i:e
  129.  
  130.             will expand to
  131.  
  132.         echo d: \dir\sub filename ext
  133.  
  134.     effectively breaking up the fully qualified file specification
  135.     into its component parts.  This logic fails if the lowest 
  136.     component is not a file name:
  137.  
  138.     Assuming i = d:\dir\sub
  139.  
  140.         echo $i:d $i:h:s $i:t:r $i:e
  141.  
  142.             will expand to
  143.  
  144.         echo d: \dir sub
  145.  
  146.     which may not be the desired result.
  147.  
  148.     Version 4 and above handles this instance correctly:
  149.  
  150.     Assuming i = d:\dir\sub
  151.  
  152.         echo $i:d $i:p $i:f:r $i:f:e
  153.  
  154.             will expand to
  155.  
  156.         echo d: \dir\sub 
  157.  
  158.     and will result in the same output as above when the lowest
  159.     component of the specification is a file name:
  160.  
  161.     Assuming i = d:\dir\sub\filename.ext
  162.  
  163.         echo $i:d $i:p $i:f:r $i:f:e
  164.  
  165.     will expand to
  166.  
  167.         echo d: \dir\sub filename ext
  168.         
  169.  
  170.     (These modifications are similar to those found in the Unix
  171.     C-shell, with enhancements for functionality under the DOS
  172.     environment;  specifically, the :d, :s, :f, :p, and :0-9 are 
  173.     artifacts of the fe program, and the :e is found in only some 
  174.     C-shell flavors.)
  175.  
  176.  
  177. fe also has several internal variables for specifying DOS special
  178. characters:
  179.  
  180.     $P =    |        $R =    >    $A =    >>
  181.     $I =    <        $Q =    "    
  182.  
  183.     Note: conflict will develop if the main loop-variable 
  184.     specified is one of these above:
  185.  
  186.         fe A ( 1 2 3 ) do echo $A
  187.  
  188.         This will produce undesired (probably) results, as
  189.         the command line generated will be "echo >>", and 
  190.         not "echo 1", "echo 2", and "echo 3".
  191.  
  192. fe also processes environment variables in the command line in a 
  193. manner similar to DOS, in that strings between sucessive percent-signs 
  194. are converted to upper-case and searched for in the environment;  if 
  195. not found, the DOS variable is stripped from the command line, else 
  196. the environment string found is inserted.
  197.  
  198. Commands
  199.  
  200. There are three ways to specify to fe the commands to execute:
  201.  
  202.     the default operation is to prompt for the commands 
  203.     (with a "? ") which are then read from standard input.
  204.  
  205.         fe i ( 1 2 3 )
  206.         ? command line 1
  207.         ? command line 2
  208.         ? end
  209.  
  210.     read the command file "comfile" if it is present on the
  211.     command line.
  212.  
  213.         fe i ( 1 2 3 ) \bat\comfile.bat arg1 arg2 ...
  214.  
  215.         within comfile.bat, %1 is substituted with arg1,
  216.         %2 with arg2, etc.
  217.  
  218.     execute the commands specified on the command line when 
  219.     they are prefixed by the keyword "do". 
  220.  
  221.         fe i ( 1 2 3 ) do command line 1 ; command line 2
  222.  
  223.         the semicolons are interpreted as newlines,
  224.         each command is processed for member-substitution
  225.         and then executed in order.
  226.  
  227. A line beginning with a colon specifies a label as in DOS batch
  228. files; this line is not executed and can be a target for a "goto" 
  229. statement.  
  230.  
  231. fe supports the DOS "if [not] exist", "if [not] str == str", 
  232. "if errorlevel X", and "goto" statements and ":str" labels.  Thus, 
  233. many simple .bat files can be executed using fe.  In addition, fe
  234. also provides additional tests and allows these substitutions:
  235.  
  236.     If Phrase      Substitution
  237.  
  238.     errorlevel    = e    same as DOS
  239.     exist        = x    same as DOS (test dirs = FALSE)
  240.     not        = !    same as DOS
  241.     isdir        = d    TRUE if name is directory
  242.     iszero        = z    TRUE if name is file and is zero size
  243.  
  244.     Branch Control      Meaning
  245.  
  246.     continue    = skip remaining commands, process next member
  247.     next        = (same as above)
  248.     restart        = process commands again using current member
  249.     redo        = (same as above)
  250.     ret         = exit program, return to DOS last LOGIC test (0 or 1)
  251.     ret e        = exit program, return to DOS last ERRORLEVEL
  252.     ret N        = exit program, return to DOS N= value 
  253.  
  254. This shortens the length of scripts or "do" commands:
  255.  
  256.     if errorlevel 1        = if e 1
  257.     if exist file.ext    = if x file.ext
  258.     if not exist file.ext    = if ! x file.ext
  259.  
  260. Note: internal DOS commands, such as DIR and DEL, always return 0.
  261. The fe program uses the "spawnl()" function to execute external
  262. .exe and .com programs, and the "system()" function to execute ".bat"
  263. programs and those commands not found in the PATH.  
  264.  
  265. Also, fe returns to DOS the value of the last "if" test, where a TRUE
  266. is returned as 1, and FALSE is returned as 0.  Further, the expression
  267. "ret N" where N is the value to return to DOS, exists, and so fe can be 
  268. used for more sophisticated testing than is available through DOS in a 
  269. .bat file, yet allow the branching from within that .bat file:
  270.  
  271.     if "%1" == "" goto quit
  272.  
  273.     fe do if d %1 ret 3 ; if z %1 ret 2 ; if x %1 ret 1 
  274.     if errorlevel 3 goto isadir    (if "isdir" is TRUE,     return 3)
  275.     if errorlevel 2 goto iszfile    (if "iszero" is TRUE,     return 2)
  276.     if errorlevel 1 goto isafile    (if "exist" is TRUE,     return 1)
  277.     echo %1 does not exist        (last logic was FALSE,     return 0)
  278.     goto quit
  279.  
  280.     :isadir
  281.     echo %1 is a directory
  282.     goto quit
  283.  
  284.     :iszfile
  285.     echo %1 is a null file
  286.     goto quit
  287.  
  288.     :isafile
  289.     echo %1 is a normal file
  290.     goto quit
  291.  
  292.     :quit
  293.  
  294.  
  295. Attempts to set environment variables are intercepted and not sent
  296. to command.com via the system call .  Unfortunately, there appears to 
  297. be a defect in the MSC6.0 libraries such that putenv() and getenv() 
  298. fail.  Specifically, getenv() functions properly until a putenv() is 
  299. issued, in which case the variable affected is then unavailable for 
  300. recall.  Further, assuming it was already set in the environment, when 
  301. "set" is passed to command.com using "system" (which should result in 
  302. the output of all variables and their values), only the variables that 
  303. appeared in the environment before the one that was modified appear.
  304.  
  305.  
  306. Examples 
  307.  
  308. This command displays the value of an environment variable:
  309.  
  310.     fe do echo %tmp%
  311.     
  312.     This .bat file will display the values of environment variables:
  313.  
  314.         @echo off
  315.         fe i ( %1 %2 %3 %4 %5 %6 %7 %8 %9 ) do echo %%$i%%
  316.  
  317.     Note the use of multiple %'s;  to prevent substitution at the
  318.     DOS interpreter level, use %% to pass a % to fe.
  319.  
  320.     Assuming this file is named "shw.bat", the syntax would be:
  321.  
  322.         C> shw path tmp
  323.         c:\bat;c:\bin;c:\usr\bin;c:\dos;c:\utl
  324.         d:\tmp
  325.  
  326. Notoriously missing from DOS is a "copy" command that will copy files to
  327. multiple disks, pausing for a disk change when the disk becomes full:
  328.  
  329.     fe ( *.* )             // for all entries
  330.     ? if isdir $i next        // if a directory, next member
  331.     ? echo $i             // display name of file 
  332.     ? copy $i a:$i             // copy to destination
  333.     ? if exist a:$i next        // if copy succeeded, next member
  334.     ? pause             // pause for disk change
  335.     ? restart            // restart command sequence
  336.  
  337.     A more sophisticated script might detect if the file is too
  338.     big to fit on a diskette or the file is of zero size (otherwise, 
  339.     an endless loop is entered), and perhaps start a command shell 
  340.     to perform other tasks in response to input can be built.
  341.  
  342.     Here is the same as above, on one line:
  343.  
  344.     fe ( *.* ) do if d $i next ; copy $i a:$i ; if x a:$i next ; pause ; restart
  345.  
  346.     Here is a batch file to do the same, only more robust:
  347.  
  348.     ===
  349.     @echo off
  350.     if "%debug%" == "yes" echo on
  351.     if "%2" == "" goto syntax
  352.  
  353.     if not exist %1 goto nofile
  354.     if not exist %2.\nul goto nodest
  355.  
  356.     fe i ( %1 ) do if d $i next ; copy $i %2$i:t ; if z $i type nul$R%2$i:t ; if x %2$i:t next ; pause ; redo
  357.     goto quit
  358.  
  359.     :syntax
  360.     echo Syntax: mcopy filespec drive:[path\]
  361.     echo filespec= DOS "wildcard" pattern
  362.     echo drive= destination drive, with ":", and an optional path
  363.     echo Copy all files from filespec onto drive/path.
  364.     echo Create zero-length files, since copy does not copy those.
  365.     echo Gets into an endless loop if a file is bigger than a disk.
  366.  
  367.     :nofile
  368.     echo mcopy error: no files matching %1 
  369.     goto quit
  370.  
  371.     :nodest
  372.     echo mcopy error: %2 is not a directory, or no trailing backslash
  373.     goto quit
  374.  
  375.     :quit
  376.     ===
  377.  
  378.     Since DOS does not expand the wildcard on the command line to
  379.     a batch file, %1 is the filespec and %2 is the drive.  The program
  380.     then attempts to copy each of the files matched in filespec to
  381.     %2$i:t (%2= drive:, $i:t= tail end of filename).  Thus, this .bat
  382.     file can handle:
  383.  
  384.         mcopy \usr\sound\*.wav a:
  385.  
  386.  
  387. This command will generate a list of 256 "    DB XXX " statements
  388.  
  389.     fe i ( 000-255 ) do pipe \t DB $i >> dbdef.inc
  390.  
  391. This command will generate a file of the first 256 bytes:
  392.  
  393.     fe i ( 000-255 ) do | dectohex h | tobin -o 256b.bin
  394.  
  395. List files by extension:
  396.  
  397.     --- File: lext.bat ---
  398.  
  399.     fe i ( %1 %2 %3 %4 %5 ) do echo $i:e | sort -u | fe j -l- do ls "*.$j"
  400.  
  401.     --- End of File ---
  402.  
  403.     foreach directory entry, echo the extension, and send to
  404.     sort to output the unique extensions, and send to
  405.     foreach incoming extension, list the files with that extension.
  406.  
  407.     set tmp=c:\tmp
  408.     fe i ( *.* ) 
  409.         if exist $i\nul goto dodir
  410.         :dofile
  411.         echo $i >> %tmp%\file.lst
  412.         goto skip
  413.         :dodir
  414.         echo $i >> %tmp%\dir.lst
  415.         goto skip
  416.         :skip
  417.  
  418.     set clopt=-Zi -AL -Od
  419.     fe i ( *.c )
  420.         if not exist $i:r.obj goto compile
  421.         echo $i is already compiled 
  422.         goto next
  423.         :compile
  424.         cl -c %CLOPT% $i
  425.         :next
  426.         
  427.  
  428. Or this batch file will copy a number of diskettes into numbered directories:
  429.  
  430.     --- File: mdcopy.bat ---
  431.     @echo off
  432.  
  433.     fe i ( 0-%1 ) do echo Disk # $i ; pause ; mkdir %2$i xcopy a: %2$i /s
  434.  
  435.     rem Syntax: mdcopy N [name]
  436.     rem N     - number of disks to copy
  437.     rem name  - optional name to prepend to number
  438.     rem This program makes a series of numbered directories,
  439.     rem and copies the diskette in drive A into each directory.
  440.     rem The "name" is used, if specified.
  441.  
  442.     --- End of file ---
  443.  
  444.     
  445. To compile a bunch of files and copy the objects to floppy:
  446.  
  447.     fe file ( *.c ) 
  448.         rm -f $i:r.obj
  449.         cl -c -Zi -Od $file 
  450.         if not exist $file:r.obj goto error
  451.         copy $file:r.obj a:
  452.         continue
  453.         :error
  454.         echo Error during compile of $file
  455.         echo $file:r.obj was not generated
  456.         
  457.  
  458. To list today's files only, this makes a good batch file:
  459.  
  460.     --- ltoday.bat ---
  461.     @echo off
  462.     if "%debug%" == "yes" echo on
  463.  
  464.     dt | fe i -l- do ls -l %1 %2 %3 %4 %5 $P grep $i
  465.     -- end of file --
  466.  
  467.     Note: dt is another Shark program that outputs date and time
  468.     in templatic fashion, and ls is still another Shark program
  469.     that lists directory entries.
  470.  
  471.     dt outputs today's date in "ls -l" format, so this fe command
  472.     executes "ls -l args" and pipes the output to "grep mm/dd/yy",
  473.     resulting in only those files with today's date.  This is an
  474.     instance of using fe with only one member (the date), running
  475.     a program and piping it from with fe to another program that
  476.     uses the member piped in.
  477.  
  478. DOS Reports
  479.  
  480. While goofing around with this program and other Shark utilities, 
  481. the following abnormalities were found.
  482.  
  483.     if exist a:\dir\\nul 
  484.  
  485.         This will return TRUE, but
  486.  
  487.     copy file a:\dir\\file
  488.  
  489.         will fail with "Path not found"
  490.     
  491.  
  492. Caveats
  493.  
  494. The number of commands and members are fixed, and are sufficiently
  495. large to support most scripts and member-lists (512, 2048 respectively).
  496. This should be optimized for the different scenarios (commands from the
  497. command line: maximum 12, no members: maximum 1).  The script buffer
  498. is fixed at 16K, but is reduced to the actual size required before 
  499. command execution begins.  In that way the memory required for a simple
  500. fe command could be reduced from >64K to the barest minimum.
  501.  
  502. fe creates or truncates a file to store the "do" command lines, which 
  503. it then removes, named in the following manner:
  504.  
  505.     if FETMP is set in the environemt:    %fetmp%
  506.     else if TMP is set in the environment:     %tmp%\___docom.for
  507.     else                    .\___docom.for
  508.  
  509. When fe reads members or command input from standard input, subsequent 
  510. command shells or other programs reading from standard input fail.
  511.  
  512. Of course, the inability to redirect multiple lines to a program from
  513. within a .bat file (as with Unix: program << here \n input ...\n here")
  514. severely restricts the effectiveness of fe, because lengthy command
  515. scripts necessitate the use of an additional file to hold this script.
  516. An alternative was suggested wherein a block of lines within the .bat
  517. file is used to supply such:
  518.  
  519.     ===
  520.     @echo off
  521.     ...
  522.  
  523.     fe -b%0 i ( %1 ) fe1
  524.     :fe1 if isdir $i echo $i is a directory
  525.     :fe1 if iszero $i echo $i is a null file
  526.     :fe1 if exist $i echo $i is a normal file
  527.  
  528.     ...
  529.  
  530.     fe -b%0 i ( %1 ) copyunfoundfiles %2
  531.     :copyunfoundfiles if exist %1$i echo $i exists on %1
  532.     :copyunfoundfiles if ! exist %1$i copy $i %1$i
  533.  
  534.     :quit
  535.     ===
  536.  
  537.     In this instance, the -b option indicates that fe is running
  538.     from a .bat file, and so %0 (the program name from the 
  539.     command line) is searched for in the PATH, and then from
  540.     within this file, labels (lines beginning with ":") with the 
  541.     name specified on the fe command line (FE1 and FE2 in this 
  542.     example, where an fe script name would otherwise occur), are
  543.     searched for and read as command input (stripping off the 
  544.     label identifier).  
  545.  
  546.     Although the above seems to be a workable approach, the 
  547.     method is flawed if the searched-for .bat file is found
  548.     in a directory from which it was not expected.  In order to
  549.     make it foolproof, the %0 should have substituted instead
  550.     the full pathname of the .bat file being executed;  this is
  551.     still an improvement over requiring an additional script file:
  552.  
  553.     fe -bc:\bat\safecopy.bat i ( %1 ) fe1
  554.     fe -bc:\bat\safecopy.bat i ( %1 ) fe2 %2
  555.  
  556.     Even more unelegant is the supplying of %2 on the fe command
  557.     line, and having it interpreted in the fe script as %1.  Of
  558.     course, an alternative is to provide a dummy %1 and then 
  559.     refer to the %2 on the command line as %2 in the fe script.
  560.  
  561.     Regardless, the approach is still under study (perhaps skipping
  562.     the %0 and instead searching back through memory blocks until
  563.     that one which spawned "fe" is found, then finding the program
  564.     name including the path and searching that file for :command 
  565.     labels).
  566.     
  567.  
  568.  
  569.  
  570. =======================================================================
  571.  
  572. fe - copyright SHARK 1991 - Programmer Bart Crane
  573. All Rights Reserved - Distribution Encouraged 
  574. Software Provided As Is, No Warranty Express Or Implied 
  575.  
  576. For More Information on SHARK, Upgrades, and other Utilities:
  577.  
  578.     Shark BBS:     (415) 969-6600
  579.  
  580.     Mail: 
  581.  
  582.     SHARK
  583.     922 San Leandro Ave. Suite C
  584.     Mountain View, CA  94043
  585.     Telephone:     (415) 969-3015
  586.     Fax:         (415) 969-6600
  587.  
  588.     Mediavision BBS:
  589.  
  590.     (415) 770-0968    - Messages To: Bart Crane
  591.  
  592.  
  593.