home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / EXEC.ZIP / exec.cmd
OS/2 REXX Batch file  |  1993-04-20  |  19KB  |  527 lines

  1. /* -----------------------------------------------------------------------
  2.  
  3.          Title: EXEC
  4.  
  5.         Author: Ralf Hauser
  6.  
  7.           Date: 14-04-93 / 14-04-93
  8.  
  9.         Manually generated by Ralf Hauser (c│o), 7400 Tübingen
  10.         e-mail: affie@frege.sns.neuphilologie.uni-tuebingen.de
  11.  
  12.    Description: Execute a series of commands on a set of specified files
  13.  
  14.       Language: REXX
  15.  
  16.   Requirements: OS/2 Version 2.x or Version 1.3 (not tested for V1.3)
  17.  
  18.         This program is declared as FREEWARE!!!
  19.  
  20.         This program may be copied and distributed to anybody without
  21.         any restrictions!!!
  22.  
  23. --------------------------------------------------------------------------
  24.  
  25.         Read this instead of a separate documentation file:
  26.  
  27.            EXEC allows you to execute a series of commands on a specified
  28.            set of files.
  29.            Each file and each command may be queried whether it is to be
  30.            processed or not.
  31.            The filespec may contain wildcards and files in subdirectories.
  32.            Commands may be given as command line arguments or within a
  33.            file.
  34.            Several switches control the program's behaviour.
  35.  
  36.            The general syntax is:
  37.  
  38.               EXEC [-switches] [attributes] filespec commandlist
  39.  
  40.            The following switches are available:
  41.  
  42.               ?     display a help screen
  43.  
  44.               !     do not confirm each file. The default is to confirm
  45.                     each file!
  46.  
  47.               a     set attributes for search. These attributes must be
  48.                     specified as the next argument.
  49.                     (For a complete discussion of these flags refer to
  50.                     the OS/2 REXX manual under function 'SysFileTree'.
  51.                     No time to explain this here. If you want to use it,
  52.                     read this section!)
  53.  
  54.               c     confirm each command to be executed. Default is to
  55.                     execute all commands without confirmation.
  56.  
  57.               f     execute commands in specified file. Instead of giving a
  58.                     'commandlist' a filename must be specified for a file
  59.                     containing all commands on a line-per-line basis.
  60.                     Multiple commands on a line may be spearated by a
  61.                     semicolon.
  62.  
  63.               l     display errorlevels of each command after execution.
  64.  
  65.               q     quiet mode: do not display filenames and commands as
  66.                     they are executed. The switch is ignored if any queries
  67.                     are made.
  68.  
  69.               s     recursively process subdirectories. Execute commands on
  70.                     all files matching the 'filespec' in the current directory
  71.                     and all directories below.
  72.  
  73.               v     verbose mode: a bit more information.
  74.  
  75.            The 'filespec' may contain wildcards (?, *) drives and paths.
  76.  
  77.            The 'commandlist' may contain multiple commands separated by
  78.            semicolons. Each command may contain variables which are expanded
  79.            at runtime.
  80.  
  81.            The following variable are available:
  82.  
  83.               $F    expands to the complete filename
  84.               $N    expands to the filename without path/drive
  85.               $D    expands to the drive of the filename
  86.               $E    expands to the (DOS style) filename extension.
  87.                     (The last string in the filename beginning with a period.)
  88.                     (The period is part of the extension.)
  89.               $B    base filename without extension
  90.               $C    comment - the rest of this comand line is ignored
  91.  
  92.            Examples:
  93.  
  94.               ■ Delete specific files of a specified directory "C:\TMP"
  95.                 and all its subdirectories:
  96.  
  97.                       EXEC  -s  C:\tmp\*  del $f
  98.  
  99.                 This executes the command "del $f" on all files in "C:\tmp"
  100.                 and its subdirectories after a query (!).
  101.  
  102.               ■ Delete specific files of a specified directory "C:\TMP"
  103.                 and all its subdirectories after they have been viewed:
  104.  
  105.                       EXEC  -cs  C:\tmp\*  type $f;del $f
  106.  
  107.                 This executes the command "type $f" on all files in "C:\tmp"
  108.                 and its subdirectories and - after a query (!) - deletes
  109.                 the corresponding file.
  110.  
  111.               ■ Copy all "*.DAT" files of a specified directory "C:\DATA"
  112.                 to a new directory "D:\NEW" and precede all files by
  113.                 their filename. Rename files to "*.TXT".
  114.                 The commands to do that are kept in file "D:\commands".
  115.  
  116.                       EXEC  -f! C:\data\*.DAT D:\commands
  117.  
  118.                 The contents of "D:\commands" is:
  119.  
  120.                       $C create header for each file
  121.                       echo "******" > D:\NEW\$b.TXT
  122.                       echo $n > D:\NEW\$b.TXT
  123.                       echo "******" > D:\NEW\$b.TXT
  124.                       type $f > D:\NEW\$b.TXT
  125.  
  126.                 Note the term "$b.TXT" which results in a new filename
  127.                 'basefilename + new extension'.
  128.  
  129. --------------------------------------------------------------------------
  130.  
  131.         If you consider this program as being useful give it to your
  132.         friends or any other OS/2 users.
  133.  
  134.                                          "OS/2 - Walking and chewing gum."
  135.  
  136. --------------------------------------------------------------------------
  137. History:
  138. 14-04-92   co Created.
  139. -------------------------------------------------------------------------- */
  140.  
  141. '@ECHO OFF'                       /* do not display any SHELL commands */
  142. global. = ""                      /* init */
  143.  
  144. /* ----------------------------------------------------------------------- */
  145. /*      Main                                                               */
  146. /* ----------------------------------------------------------------------- */
  147.  
  148. Main :
  149.         CALL main_init            /* initialize global data structures */
  150.  
  151.         /*
  152.          *    handle arguments
  153.          */
  154.  
  155.         PARSE ARG switches filespec commands
  156.  
  157.         IF ARG() = 0 THEN
  158.            CALL main_help
  159.  
  160.         /* header */
  161.         Say " "
  162.         CALL main_msg "   V" || global.version
  163.         Say " "
  164.  
  165.         /* look whether we have command line options (switches) */
  166.         IF Substr(switches, 1, 1) <> "-" & Substr(switches, 1, 1) <> "/" THEN DO
  167.            /* no, so shift arguments */
  168.            PARSE ARG filespec commands
  169.            END
  170.         ELSE DO /* handle switches */
  171.            IF Pos("?", switches) > 0 THEN
  172.               CALL main_help
  173.            IF Pos("!", switches) > 0 THEN
  174.               global.query_file = 0
  175.            IF Pos("a", switches) > 0 THEN
  176.               PARSE ARG switches filespec global.attributes commands
  177.            global.query_exec= Pos("c", switches)
  178.            global.comfile   = Pos("f", switches)
  179.            global.errcodes  = Pos("l", switches)
  180.            global.quiet     = Pos("q", switches)
  181.            global.subdirs   = Pos("s", switches)
  182.            global.verbose   = Pos("v", switches)
  183.            END
  184.  
  185.         /* consistency check */
  186.         IF global.query_exec <> 0 THEN
  187.            global.quiet = 0
  188.         IF global.query_file <> 0 THEN
  189.            global.verbose = 1
  190.  
  191.         /* check correct arguments */
  192.         IF filespec = "" | commands = "" THEN
  193.            CALL main_help
  194.  
  195.         /*
  196.          *    convert specified commands to list
  197.          */
  198.  
  199.         CALL main_convert_commands commands
  200.  
  201.         /*
  202.          *    create a list of files
  203.          */
  204.  
  205.         CALL main_filelist filespec
  206.  
  207.         /*
  208.          *    process commands on filelist
  209.          */
  210.  
  211.         num_of_execs = main_exec()
  212.  
  213.         /*
  214.          *    Finished!
  215.          */
  216.  
  217.         SAY ""
  218.         CALL main_msg global.files.0 "File(s) handled."
  219.         CALL main_msg num_of_execs "File(s) processed. Program terminated successfully"
  220.         /* CALL beep 1600, 200 */
  221.         /* CALL beep 2000, 200 */
  222.         /* CALL beep 2400, 200 */
  223. EXIT
  224.  
  225. /* end: main */
  226.  
  227. /* ----------------------------------------------------------------------- */
  228. /*      main_init                                                          */
  229. /* ----------------------------------------------------------------------- */
  230.  
  231. main_init : PROCEDURE EXPOSE global.
  232. /*
  233.  *      initializes all global data
  234.  */
  235.         /* check whether RxFuncs are loaded, if not, load them */
  236.         IF RxFuncQuery('SysLoadFuncs') THEN DO
  237.            /* load the load-function */
  238.            CALL RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  239.            /* load the Sys* utilities */
  240.            CALL SysLoadFuncs
  241.            END
  242.  
  243.         /* set default values */
  244.         global.title         = "EXEC"
  245.         global.version       = "1.00"
  246.         global.attributes    = "*-**-"      /* archives or not - who cares */
  247.                                             /* no directories */
  248.                                             /* hiden or not - who cares */
  249.                                             /* read-only or not - who cares */
  250.                                             /* no system files */
  251.         global.query_file    = 1
  252.         global.query_exec    = 0
  253.         global.subdirs       = 0
  254.         global.comfile       = 0
  255.         global.errcodes      = 0
  256.         global.verbose       = 0
  257.         global.quiet         = 0
  258.         global.no_colors     = 0
  259.  
  260.         global.files.        = ""
  261.         global.files.0       = 0
  262.         global.filename_offset = 38
  263.  
  264.         global.commands.     = ""
  265.         global.commands.0    = 0
  266.  
  267.         RETURN
  268. /* main_init */
  269.  
  270. /* ----------------------------------------------------------------------- */
  271. /*      main_error                                                         */
  272. /* ----------------------------------------------------------------------- */
  273.  
  274. main_msg : PROCEDURE EXPOSE global.
  275. PARSE ARG msg
  276.  
  277.         Say global.title || ": " || msg
  278.         RETURN
  279. /* end: main_msg */
  280.  
  281. /* ----------------------------------------------------------------------- */
  282. /*      main_error                                                         */
  283. /* ----------------------------------------------------------------------- */
  284.  
  285. main_error : PROCEDURE EXPOSE global.
  286. PARSE ARG msg, msg1, msg2
  287.  
  288.         Say " "
  289.         CALL main_msg "An error occured:"
  290.         CALL Beep 500, 200
  291.         CALL Beep 900, 200
  292.         CALL Beep 500, 200
  293.         Say " "
  294.         Say "   Error: " || msg
  295.         IF msg1 <> "" THEN
  296.            Say "          " || msg1
  297.         IF msg2 <> "" THEN
  298.            Say "          " || msg2
  299.         EXIT
  300. /* end: main_error */
  301.  
  302. /* ----------------------------------------------------------------------- */
  303. /*      main_help                                                          */
  304. /* ----------------------------------------------------------------------- */
  305.  
  306. main_help : PROCEDURE EXPOSE global.
  307. /*
  308.  *      Print a help screen
  309.  */
  310.         Say " Usage: " || global.title || " [{/|-}switches]  [attributes] filespec  command"
  311.         Say " "
  312.         Say "     Possible switches are:"
  313.         Say " "
  314.         Say "         ?     this help"
  315.         Say "         !     do not confirm each file (default is to confirm)"
  316.         Say "         a     set attributes for search (Flags: ADHRS, *+-)"
  317.         Say "         c     confirm each command to be executed"
  318.         Say "         f     execute commands in spec. file"
  319.         Say "         l     display errorlevels"
  320.         Say "         q     quiet mode"
  321.         Say "         s     recursively process subdirectories"
  322.         Say "         v     verbose mode"
  323.         Say " "
  324.         Say "     The following variables may be used within commands:"
  325.         Say " "
  326.         Say "         $F    complete filename"
  327.         Say "         $N    filename without path"
  328.         Say "         $B    (base) filename without extension"
  329.         Say "         $D    drive of filename"
  330.         Say "         $E    filename extension (with dot)"
  331.         Say "         $C    comment - rest of line is ignored"
  332.  
  333.         EXIT
  334. /* end: main_help */
  335.  
  336. main_convert_commands : PROCEDURE EXPOSE global.
  337. /*
  338.  *      convert specified commands to list
  339.  *      a list of command may contain commands separated by commas
  340.  */
  341. PARSE ARG cmds
  342.  
  343.         IF global.comfile <> 0 THEN DO
  344.            /* we have a filename for a file containing a list of commands */
  345.            filename = cmds
  346.            IF (Stream(filename, "C", "OPEN READ") <> "READY:") THEN
  347.               CALL main_error "Could not open '" || filename || "' for reading"
  348.  
  349.            /* read commandfile */
  350.            linenum  = 0
  351.            DO UNTIL lines(filename) = 0
  352.               buffer = Linein(filename)
  353.               /* process each line being read */
  354.               CALL main_convert_command_line buffer
  355.            END
  356.            /* close file - no longer needed */
  357.            CALL Stream filename, "C", "CLOSE"
  358.            END
  359.         ELSE
  360.            /* collect all commands */
  361.            CALL main_convert_command_line cmds
  362.         RETURN
  363. /* end: main_convert_commands */
  364.  
  365. main_convert_command_line : PROCEDURE EXPOSE global.
  366. /*
  367.  *      convert spec. list of commands to a global list of separate commands
  368.  *      a list of command may contain commands separated by commas
  369.  */
  370. PARSE ARG cmds
  371.  
  372.         num_of_cmds = global.commands.0 + 1           /* commands so far */
  373.         DO FOREVER
  374.            idx = Pos(";", cmds)
  375.            IF idx = 0 THEN DO
  376.               global.commands.num_of_cmds = cmds
  377.               LEAVE                                   /* break loop */
  378.               END
  379.            ELSE DO
  380.               global.commands.num_of_cmds = Left(cmds, idx - 1)
  381.               num_of_cmds = num_of_cmds + 1
  382.               END
  383.            cmds = Substr(cmds, idx + 1)
  384.            END /* end-of-do-forever */
  385.  
  386.         global.commands.0 = num_of_cmds
  387.         RETURN
  388. /* end: main_convert_command_line */
  389.  
  390. main_filelist : PROCEDURE EXPOSE global.
  391. /*
  392.  *      create a filelist
  393.  */
  394. PARSE ARG filespec
  395.  
  396.         IF global.subdirs <> 0 THEN
  397.            searchcode = "FS"                          /* files and subdirs */
  398.         ELSE
  399.            searchcode = "F"                           /* files only */
  400.  
  401.         CALL SysFileTree filespec, "global.files", searchcode, global.attributes
  402.  
  403.         IF global.files.0 = 0 THEN
  404.            CALL main_msg "No files found for filespec '" || filespec || "' (" || global.attributes ")"
  405.  
  406.         RETURN
  407. /* end: main_filelist */
  408.  
  409. main_exec : PROCEDURE EXPOSE global.
  410. /*
  411.  *      execute the specified commands on filelist
  412.  */
  413.         num_of_execs = 0
  414.  
  415.         /* process each file */
  416.         DO i=1 to global.files.0
  417.            filename = Translate(Substr(global.files.i, global.filename_offset))
  418.            handled  = 0
  419.  
  420.            IF global.verbose <> 0 THEN
  421.               SAY "file:" filename "   " Left(global.files.i, global.filename_offset - 1)
  422.  
  423.            /* extract filename extension */
  424.            extension       = ""
  425.            filename_nopath = ""
  426.            filename_nopath = Filespec("N", filename)
  427.            basename        = filename_nopath
  428.            extension_pos   = Lastpos(".", filename_nopath)
  429.            IF extension_pos > 0 THEN DO
  430.               extension = Substr(filename_nopath, extension_pos)
  431.               basename  = Left(filename_nopath, extension_pos - 1)
  432.               END
  433.  
  434.            file_is_to_be_handled = 1                  /* assume: yes */
  435.            IF global.query_file <> 0 THEN
  436.               file_is_to_be_handled = query("file")
  437.  
  438.            IF file_is_to_be_handled <> 0 THEN DO
  439.               /* process each command */
  440.               DO j=1 to global.commands.0
  441.                  cmd = Translate(global.commands.j)
  442.                  /* replace variables used within command */
  443.                  idx = Pos("$C", cmd)
  444.                  IF idx > 0 THEN
  445.                     cmd = Left(cmd, idx - 1)
  446.                  cmd = replace(cmd, filename,                "$F")
  447.                  cmd = replace(cmd, extension,               "$E")
  448.                  cmd = replace(cmd, basename,                "$B")
  449.                  cmd = replace(cmd, filename_nopath,         "$N")
  450.                  cmd = replace(cmd, Filespec("D", filename), "$D")
  451.                  cmd = replace(cmd, Filespec("P", filename), "$P")
  452.                  /* is cmd still valid? */
  453.                  IF cmd <> "" THEN DO
  454.                     IF global.quiet = 0 THEN
  455.                        SAY "exec:" cmd
  456.  
  457.                     exec_is_to_be_done = 1
  458.                     IF global.query_exec <> 0 THEN
  459.                        exec_is_to_be_done = query("command")
  460.  
  461.                     IF exec_is_to_be_done <> 0 THEN DO
  462.                        handled = 1
  463.                        /* execute command */
  464.                        CMD
  465.  
  466.                        IF global.errcodes <> 0 THEN
  467.                           SAY " Errorcode: " rc
  468.  
  469.                        END /* e-o-if exec */
  470.                     END /* e-o-if cmd <> "" */
  471.                  END /* e-o-do commands */
  472.               END /* e-o-if query */
  473.  
  474.            IF handled = 1 THEN
  475.               num_of_execs = num_of_execs + 1
  476.            IF global.verbose <> 0 THEN
  477.               SAY ""
  478.         END /* e-o-do files */
  479.  
  480.         RETURN num_of_execs
  481. /* end: main_exec */
  482.  
  483. replace : PROCEDURE
  484. /*
  485.  *      replace within the specified string the source pattern by the target pattern
  486.  */
  487. PARSE ARG string, target, source
  488.  
  489.         idx = Pos(source, string)
  490.         IF idx > 0 THEN DO
  491.            string = Delstr(string, idx, Length(source))
  492.            string = Insert(target, string, idx - 1)
  493.            END
  494.  
  495.         RETURN string
  496. /* end: replace */
  497.  
  498. query : PROCEDURE EXPOSE global.
  499. /*
  500.  *      Query whether item is to be handled or not
  501.  */
  502. PARSE ARG item
  503.  
  504.         Say "confirm" item "with <enter>; ignore with <space>; abort with <esc>"
  505.         DO FOREVER
  506.            c = C2d(SysGetKey("NOECHO"))
  507.            SELECT
  508.              WHEN c = 13 THEN /* ENTER */
  509.                   RETURN 1
  510.  
  511.              WHEN c = 32 THEN /* SPACE */
  512.                   RETURN 0
  513.  
  514.              WHEN c = 27 THEN DO /* ESC */
  515.                   CALL main_msg "Program aborted by user"
  516.                   EXIT
  517.                   END
  518.  
  519.              OTHERWISE
  520.                   CALL Beep 100, 50
  521.              END /* e-o-select */
  522.            END /* e-o-do-forever */
  523. /* end: query */
  524.  
  525. /* <EOF> */
  526.  
  527.