home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / dirtools.zip / copydir.cmd next >
OS/2 REXX Batch file  |  1999-12-13  |  19KB  |  696 lines

  1. /* CopyDir.CMD -- A utility to robustly copy a directory tree.
  2. Created by: Daniel Hellerstein (danielh@econ.ag.gov), 08 Nov 1998
  3. Requires: The REXXLIB library (which may be included in the distribution
  4.           file)
  5.  
  6. Usage. From an OS/2 command prompt:
  7.     COPYDIR  source_dir dest_dir  [-opt] 
  8.  
  9. where:
  10.    source_dir --  source directory 
  11.    dest_dir   --  destination directory
  12.    [-opt ]   -- list of options.
  13.  
  14. Options include:
  15.   -8   --  Always convert "long" (HPFS) style file names to unique
  16.            8.3 (FAT) names; even if destination drive can support
  17.            long file names.
  18.   -Q   --  Quiet mode 
  19.   -QQ  --  Very quite mode
  20.   -R   --  Replace mode. If /R not specified, then newer files will
  21.            not be overwritten. 
  22.   -NOCHECK -- Do not check if destination drive has enough space
  23.   -CHECK   -- Check if destination drive has enough space
  24.   -ZIP=filename -- Create directory specific filename.ZIP files on the
  25.                    the destination drive, with each  of these ZIP files
  26.                    containing the contents of the source directory. 
  27. Notes:
  28.   * these options can override the user changable parameters
  29.     discussed below.
  30.   * if the destination drive is FAT, the 8.3 conversion of filenames 
  31.     will always be done (if necessary).  
  32.   * when an 8.3 conversion occurs, a name of the form  XXXXXnnn.EXT is
  33.     used; where XXXXX is the first 5 characters of the source file's name,
  34.     nnn is an integer from 001 to 999, and EXT is the first 3 characters
  35.     of the source file's extension.  
  36.   * If a long directory name is encountered, the directory's contents will NOT
  37.     be copied.
  38.   * If a bad sector (or some other form of error) prevents copying
  39.     a file, the file will be skipped (that is, COPYDIR will try and
  40.     copy the other files).
  41.   * By default, if any problems occur a file with the name COPYDIR.ERR is 
  42.     created. This file (located in the directory containing COPYDIR.CMD)
  43.     signifies the problems -- such as a "failure to copy a file" or
  44.     "longname converted".  
  45.   * If there is not enough room on the destination drive, you will
  46.     be asked to "continue anyways". Note that this "not enough room"
  47.     calculation is made without accounting for the possiblitiy of 
  48.     overwriting a file, hence is conservative.
  49.   * If the source and target directory may contain spaces, be sure to place the
  50.     directory name between " characters. 
  51.   * If you do not include =filename after a -ZIP option,
  52.     a name derived from today's date is used. For example, 20NOV98.ZIP 
  53.     (corresponding to 20 Nov 1998)
  54.   * Note that when the -ZIP option is used, a ZIP file will be created
  55.     on the destination drive, and will be filled with files from
  56.     the corresponding source drive.  The same filename 
  57.     is used in each destination directory (though, of course, each of
  58.     these .ZIP files will contain unique content).
  59.      
  60.  
  61. Examples:
  62.    COPYDIR E:\DOCS   G:\DOCS
  63.    COPYDIR F:\GAMES\NEW   E:\FUN  -8 -CHECK -R
  64.    COPYDIR "My Docs"  "F:\archive\Old Docs" -NOCHECK
  65.    COPYDIR F:\DOCS\CURRENT  I:\ARCHIVE\Y1998  -ZIP
  66.                 
  67. */
  68.  
  69.  
  70. /*  ------------ USER changeable Parameters ---------- */
  71. /* Check if there is enough room on destination drive
  72.         =1 : Check
  73.         =0 : Do NOT check                */
  74. testsize=1
  75.  
  76. /* Verbosity:
  77.   0 = Minimal
  78.   1 = Average
  79.   2 = Lots (displays all problems) */
  80. verbose=1
  81.  
  82.  
  83. /* Fully qualified name of file to write "errors" to.  
  84.    If blank, then COPYDIR.ERR, in the directory containing COPYDIR.CMD,
  85.    is used. */
  86. errfile=''
  87.  
  88. /*  ------------ END of  USER changeable Parameters ---------- */
  89.  
  90.  
  91. /*---   Load REXX libraries ----- */
  92. /* Load up advanced REXX functions */
  93. foo=rxfuncquery('sysloadfuncs')
  94. if foo=1 then do
  95.   foo=RxFuncAdd('SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs')
  96.   if foo=0 then call SysLoadFuncs
  97. end
  98.  
  99. foo=rxfuncquery('rexxlibregister')
  100. if foo=1 then do
  101.  foo=rxfuncadd('rexxlibregister','rexxlib', 'rexxlibregister')
  102.  if foo=0 then call rexxlibregister
  103. end
  104. foo=rxfuncquery('rexxlibregister')
  105. if foo=1 then  do
  106.  say "Sorry, this utility requires the REXXLIB library "
  107.  exit
  108. end
  109.  
  110.  
  111. /* doscopy error list */
  112. doscopys.2='source file not found '
  113. doscopys.3=' source or target path not found '
  114. doscopys.5 =' target file exists but 'A' or 'R' mode not specified '
  115. doscopys.32 =' sharing violation for source or target file '
  116. doscopys.108 =' source or target drive locked '
  117. doscopys.112 = 'disk full '
  118. doscopys.206 = 'invalid source or target file name '
  119. doscopys.267 = 'source name is a directory '
  120. doscopys.282 = 'extended attributes not supported for target '
  121.  
  122.  
  123. nowdir=directory()
  124. nowdrive=filespec('d',nowdir)
  125. nowpath=filespec('p',nowdir)
  126.  
  127. fromkeyb=0
  128.  
  129. parse arg bax
  130.  
  131. if bax='' then say "Copy a directory tree (? for help)."
  132.  
  133. qq=pos('"',bax)
  134. if qq>0 then do
  135.    newbax=''
  136.    do forever
  137.        if bax='' then leave
  138.        parse var bax p1 '"' p2 '"' bax
  139.        if p2='' then do
  140.           newbax=newbax' 'p1
  141.           iterate
  142.        end /* do */
  143.        p2=translate(p2,'01'x,' ')
  144.        newbax=newbax' 'p1' 'p2
  145.    end /* do */
  146.    parse var newbax in1 in2 astuff2
  147.    in1=translate(in1,' ','01'x)
  148.    in2=translate(in2,' ','01'x)
  149. end /* do */
  150. else do
  151.   parse arg in1 in2 astuff2
  152. end
  153.  
  154. astuff2=translate(astuff2)
  155.  
  156. call getopts
  157.  
  158. if in1='?' then do
  159.    Say "Utility to copy a directory tree "
  160.    say "Usage: x:>COPYDIR fromdir todir [-opt] "
  161.    say "  Where: fromdir= source directory "
  162.    say "         todir  = target directory "
  163.    say "         [-opt]= one or more options. "
  164.    call showhelp 0
  165.    exit
  166. end /* do */
  167.  
  168. a1:
  169. if in1='' then do
  170.    fromkeyb=1           /* keyboard io */
  171.    do forever
  172.      call charout, " From what directory: "
  173.      pull fromdir
  174.      if fromdir='?' then do
  175.         say "Enter a source directory from which to copy files "
  176.         iterate
  177.      end /* do */
  178.      leave
  179.    end
  180.    say
  181. end
  182. else do
  183.    fromdir=in1
  184. end /* do */
  185. in1=''
  186.  
  187. fromdir=fixdir(fromdir,nowdrive)
  188.  
  189. if dir_exists(fromdir)=0 then do
  190.     say "No such directory: " fromdir
  191.     signal a1
  192. end
  193. else do
  194.    say " >>> Copying from: "fromdir
  195. end /* do */
  196.  
  197. fromdrive=filespec('d',fromdir)
  198.  
  199. say
  200. a2: if fromkeyb=1 then do 
  201.       do forever
  202.         call charout, "To what directory: "
  203.         pull todir
  204.         if todir='?' then do
  205.            say "Enter a destination directory, into which files will be copied."
  206.            iterate
  207.         end /* do */
  208.         say
  209.         leave
  210.      end
  211. end /* do */
  212. else do
  213.    todir=in2
  214. end /* do */
  215. in2=''
  216.  
  217.  
  218. todir=fixdir(todir,nowdrive)
  219.  
  220. todrive=filespec('d',todir)
  221.  
  222. if dir_exists(strip(todir,,'\'))=0 then do
  223.   say "No such destination directory: "todir
  224.   call charout,' Create it? (Y=yes) '
  225.   pull mkit ; mkit=left(strip(mkit),1)
  226.   say 
  227.   if mkit<>1 & mkit<>'Y' then signal a2
  228.   foo=sysmkdir2(todir)
  229. end /* do */
  230.  
  231. if fromkeyb=1 then do
  232.   do forever
  233.      say 
  234.      call charout, "   Enter -options: "
  235.      pull astuff2
  236.      if astuff2='?' then do
  237.            call showhelp 1
  238.            iterate
  239.      end /* do */
  240.      call getopts
  241.      leave
  242.   end
  243.   say 
  244. end /* do */
  245.  
  246.  
  247. if dozip=0 then
  248.   say " >>> Writing to: " todir
  249. else 
  250.   say " >>> Archiving to " zipfile " files in " todir
  251.  
  252. say " .... using Options: " astuff2
  253. say
  254.  
  255. todrivetype=dosfilesys(strip(todrive,,':'))
  256. fromdrivetype=dosfilesys(strip(fromdrive,,':'))
  257.  
  258. if trunc8=1 then do
  259.   select
  260.      when todrivetype='FAT' & fromdrivetype<>'FAT' then 
  261.         say " Caution: copying from non-FAT to FAT drive ."
  262.      when todrivetype<>'FAT' & fromdrivetype<>'FAT' then
  263.         say "Caution: copying from non-FAT to non-FAT, with 8.3 truncation "
  264.      otherwise
  265.         say "Copying from FAT drive; 8.3 truncation not required "
  266.   end
  267. end
  268. else do
  269.  if todrivetype='FAT' & fromdrivetype<>'FAT' then do
  270.    say " ** Warning: writing to a FAT drive from a non-FAT drive " 
  271.    if fromkeyb=1 then do
  272.       call charout,'    Continue (long names will be truncated). 1=Yes ?'
  273.       pull aa ;aa=left(strip(aa),1)
  274.       if aa<>1 & aa<>'Y' then exit
  275.    end /* do */
  276.    trunc8=1
  277.  end /* do */
  278. end
  279.  
  280. getit=strip(fromdir,,'\')'\*.*'
  281. wow=sysfiletree(getit,'stuff','DOS')
  282. j1=stuff.0+1
  283. stuff.j1=fromdir
  284. ieelen=length(stuff.j1)
  285. stuff.0=j1
  286.  
  287. if testsize=1 then do /* get size of this, see if enough room on target */
  288.    arf=sysdriveinfo(todrive)
  289.    parse var arf . todrivefree .
  290.    if verbose>0 then say todrive" has "||addcomma(todrivefree)||' bytes free.',
  291.         " Checking if this is sufficient ..."
  292.    ssize1=0 ;ssize2=0
  293.    wow=sysfiletree(getit,'stuff3','FS')
  294.  
  295.    do ii=1 to stuff3.0
  296.         parse var stuff3.ii d1 d2 jsize d3 aname
  297.         ssize1=ssize1+dosfileinfo(strip(aname),'s')
  298.         ssize2=ssize2+jsize
  299.    end /* do */
  300.    say "  Bytes to copy: "||addcomma(ssize2)||' ('||addcomma(ssize1)||')'
  301.    if ssize1>todrivefree then do
  302.       say "Warning: ignoring overwrites, there is not enough free space on "||todrive
  303.       if verbose<1 then exit
  304.       call charout,' Copy anyways (Y=yes)? '
  305.       pull ans; ans=left(strip(ans),1)
  306.       if ans<>'Y' & ans<>1 then exit
  307.    end /* do */
  308. end
  309.  
  310. trunc8s.0=0
  311. badcopies.0=0
  312. nfiles=0
  313. nbytes=0 ;badbytes=0 ;nbytes0=0
  314. nfiles2=0
  315. llen=0
  316. gotlong1=0
  317.  
  318. do mm=1 to stuff.0
  319.   thisdir=strip(stuff.mm,,'\')
  320.   mkit=strip(todir'\'||strip(substr(thisdir,ieelen+1),,'\'),,'\')
  321.  
  322.   foo=1
  323.   if trunc8=1 then foo=checkdir8(mkit)
  324.   if foo=0 then do /* unable to write to this directory */
  325.        nk=badcopies.0+1
  326.        badcopies.nk=stuff.mm
  327.        badcopies.nk.2=mkit
  328.        badcopies.nk.1='*.*'
  329.        badcopies.0=nk
  330.        iterate
  331.   end /* do */
  332.  
  333.   yeep=left(mm 'of 'stuff.0||") "thisdir " to " mkit '..... ',79)
  334.   if verbose>0 then say yeep
  335.  
  336.   yow=sysmkdir2(mkit)
  337.   wow=sysfiletree(thisdir'\*.*','stuff2','fo')
  338.  
  339.   llen=0
  340.   igoo=0
  341.   if dozip=1 then do
  342.      if stuff2.0=0 then iterate /* nothing to zip */
  343.      say "    ZIPping "stuff2.0 " files."
  344.      azipfile=mkit||'\'zipfile
  345.      if trunc8=1 then  azipfile=fix8(azipfile)
  346.      address cmd '@ZIP -j -q 'azipfile ' 'thisdir'\*.*'
  347.      foo=rc
  348.      nfiles=nfiles+stuff2.0
  349.      iterate           
  350.   end
  351.  
  352. /* else, copy each file */
  353.   do mmm=1 to stuff2.0 
  354.  
  355.    nfiles=nfiles+1
  356.    yee1=filespec('N',stuff2.mmm)  
  357.    targfile=mkit||'\'||yee1
  358.    targfile0=targfile
  359.    if trunc8=1 then  targfile=fix8(targfile)
  360.  
  361.    s1=stream(stuff2.mmm,'c','query datetime')
  362.    s2=stream(targfile,'c','query datetime')
  363.    if s1==s2 & replaceit<>1 then iterate
  364.  
  365.    nfiles2=nfiles2+1
  366.    fsize=stream(stuff2.mmm,'c','query size')
  367.    if datatype(fsize)<>'NUM' then do
  368.        foo=-1
  369.        fsize=0
  370.    end /* do */
  371.    else do
  372.       nbytes0=nbytes0+fsize
  373.       foo=doscopy(stuff2.mmm,targfile,'R')
  374.       fsize=dosfileinfo(stuff2.mmm,'s')
  375.       nbytes=nbytes+fsize
  376.    end
  377.    if foo<>0 then do
  378.         say
  379.         errname=doscopys.foo
  380.         if errname='DOSCOPYS.'FOO then errname='unknown error'
  381.         if verbose>0 then   say " Error copying: "yee1 '(' foo'='errname
  382.         if verbose=0 then say  " Error copying: "yee1 '(' foo
  383.         llen=80
  384.          nk=badcopies.0+1
  385.          badcopies.nk=stuff2.mmm
  386.          badcopies.nk.2=targfile
  387.          badcopies.nk.1=foo
  388.          badcopies.0=nk
  389.          badbytes=badbytes+fsize
  390.    end /* error  */
  391.    else  do
  392.      if verbose>0 then do
  393.         if targfile<>targfile0 then do
  394.               yee1=yee1' as '||filespec('n',targfile)||','
  395.               oi=trunc8s.0+1
  396.               trunc8s.oi=stuff2.mmm
  397.               trunc8s.oi.1=filespec('n',targfile)
  398.               trunc8s.oi.2=targfile
  399.               trunc8s.0=oi
  400.         end /* do */
  401.         if igoo=0 & verbose>0 then  call charout,'    : '
  402.         igoo=1
  403.         lyee1=length(yee1)
  404.         lrem=lyee1//14
  405.         yee2=yee1
  406.         if lrem>0 then do
  407.             yee2=yee1||copies(' ',14-lrem)
  408.         end /* do */
  409.         if (llen+length(yee2))>75 then do
  410.             if llen<>80 then say
  411.             llen=0; if verbose>0 then call charout ,'    : '
  412.         end /* do */
  413.         if verbose>0 then call charout,yee2' '
  414.         llen=length(yee2)+llen+2
  415.      end
  416.    end
  417.   end          /* all files */
  418.  
  419.   if verbose>0 & igoo=1 then  say
  420. end
  421. say ' ----------------- ' 
  422.  
  423. if verbose>0 then do
  424.   say " Total of " nfiles " files in " stuff.0 " directories: "
  425.   if dozip=0 then do
  426.     say "   files / bytes (allocated) copied = " nfiles2' / '||addcomma(nbytes0) ' ('|| ,
  427.            addcomma(nbytes)||')'
  428.     if badcopies.0+badbytes>0 then
  429.        say '     ....  of which ' badcopies.0' / 'badbytes' failed '
  430.   end
  431. end
  432.  
  433.  
  434. do ii=1 to badcopies.0
  435.   if verbose>1 then say badcopies.ii '( 'badcopies.ii.1
  436.   if badcopies.ii.1='*.*' then
  437.     arf.ii='COPY 'badcopies.ii||'\*.* 'badcopies.ii.2
  438.   else
  439.     arf.ii='COPY 'badcopies.ii ' 'badcopies.ii.2
  440.  
  441. end
  442.  
  443. do ii=1 to trunc8s.0
  444.     if verbose>1 then say  trunc8s.ii '(' trunc8s.ii.1
  445.     ii2=ii+badcopies.0
  446.     arf.ii2='REN 'trunc8s.ii.2 ' 'trunc8s.ii
  447. end /* do */
  448.  
  449. arf.0=badcopies.0+trunc8s.0
  450.  
  451. if arf.0>0 & verbose>0 then do
  452.   if errfile<>'' then do
  453.         goog=errfile
  454.   end /* do */
  455.   else do
  456.     parse source os type name
  457.     oo=lastpos('.',name)
  458.     if oo>0 then 
  459.          goog=left(name,oo)||'ERR'
  460.     else
  461.         goog=goog||'.ERR'
  462.   end
  463.   ii=arf.0
  464.   ii=ii+1
  465.   arf.ii='Rem COPY entries indicate files, or directories, that could not be copied '
  466.   ii=ii+1
  467.   arf.ii='Rem REN  entries indicate files with shortened file names '
  468.   arf.0=ii
  469.   foo=filewrite(goog,'arf','R')
  470.   say " Writing failures and renames to " goog
  471. end
  472.  
  473. exit
  474.  
  475.  
  476. /*************/
  477. fixdir:procedure                /* fix up directory string */
  478. parse arg fromdir,nowdrive
  479.  
  480. fromdir=strip(fromdir)
  481. if left(fromdir,1)='\' then fromdir=nowdrive||fromdir /*  \foobar */
  482.  
  483. fromdir=strip(strip(fromdir,'t','\'))
  484. sspos=pos(':',fromdir)
  485. if sspos=0 then fromdir=nowdrive||fromdir  /* no : in dir, so add X: */
  486. sspos=pos(':',fromdir)
  487. if substr(fromdir,sspos+1,1)<>'\' then do  /* x:d1\d2 */
  488.   foo=directory()
  489.   yy=left(fromdir,sspos)
  490.   woo=directory(yy)
  491.   goo=directory(foo)
  492.   parse var fromdir a1 ':' a2 
  493.   fromdir=woo'\'a2
  494. end /* do */
  495. fromdir=strip(fromdir,'t','\')
  496. if right(fromdir,1)=':' then fromdir=fromdir'\'
  497. return fromdir
  498.  
  499.  
  500. /* ------------------------------------- */
  501. sysmkdir2:procedure
  502. parse arg adir
  503.  
  504. adir=strip(adir,'t','\')
  505. ff=sysmkdir(adir)
  506. if ff=0 then return ff
  507.  
  508. /* make the tree */
  509. f2=adir'\'
  510. dd=filespec('d',f2)
  511. pp=filespec('p',f2)
  512. if pp='\' | pp='' then return -1
  513.  
  514. pp2=strip(translate(pp,' ','\'))
  515.  
  516. do mm=1 to words(pp2)
  517.    a1=subword(pp2,1,mm)
  518.    a1=translate(a1,'\',' ')
  519.    dd2=dd'\'a1
  520.    hoo=sysmkdir(dd2)
  521.    if hoo=0 then say ' ... creating: 'dd2  
  522. end /* do */
  523.  
  524. return hoo
  525.  
  526.  
  527.  
  528. /************/
  529. /* ADD COMMAS TO A NUMBER */
  530. addcomma:procedure
  531. parse arg aval,ndec
  532. parse var aval p1 '.' p2
  533.  
  534. if ndec='' then do
  535.    p2=''
  536. end
  537. else do
  538.    p2='.'||left(p2,ndec,'0')
  539. end /* do */
  540.  
  541. plen=length(p1)
  542. p1new=''
  543. do i=1 to 10000 while plen>3
  544.    p1new=','right(p1,3)||p1new
  545.    p1=delstr(p1,plen-2)
  546.    plen=plen-3
  547. end /* do */
  548.  
  549. return p1||p1new||p2
  550.  
  551.  
  552. /**********/
  553. /* convert hpfs long file names to some kind of fat name */
  554. fix8:procedure
  555. parse arg aname
  556.  
  557. t1=filespec('d',aname)
  558. t2=filespec('p',aname)
  559. t3=filespec('n',aname)
  560.  
  561. parse var t3 t3a '.' t3b
  562.  
  563. select
  564.    when pos(' ',t3)>0 then not8=1
  565.    when pos('.',t3b)>0 then not8=1
  566.    when length(t3a)>8 then not8=1
  567.    when length(t3b)>3 then not8=1
  568.    otherwise not8=0
  569. end
  570.  
  571. if not8=0  then return aname
  572.  
  573. /* else, it's a non-fat allowable name --- create a new name */
  574. /* first, replace ' ' with _ */
  575. t3a=translate(t3a,'_',' ')
  576. t3b=translate(t3b,'__','. ')
  577.  
  578.  
  579. if length(t3a)>8 | length(t3b)>3 then do
  580.    t3a=left(t3a,min(length(t3a),5))'???'
  581. end /* do */
  582.  
  583. if length(t3b)>3 then t3b=left(t3b,3)
  584.  
  585. t3=t3a
  586. if t3b<>'' then t3=t3a'.'t3b
  587.  
  588. newname=dostempname(t1||t2||t3)
  589. return newname
  590.     
  591. /**********/
  592. /* check for 8 character max in directory names */
  593. checkdir8:procedure
  594. parse arg aa
  595. aa0=aa
  596. if (pos(' ',aa)+pos('.',aa))>0  then do
  597.    say "Caution:ERROR: converting . or space to _ in directory: " aa0
  598.    aa=translate(aa,'__',' .')
  599. end /* do */
  600. aa=translate(aa,' ',':\')
  601. do mm=1 to words(aa)
  602.    if length(word(aa,mm))>8 then do
  603.      say "ERROR: Unable to create longname directory on FAT drive: " aa0
  604.      return 0
  605.   end /* do */
  606. end
  607. return 1
  608.  
  609.  
  610. /**********/
  611. getopts:
  612. if pos('-Q',astuff2)>0 then verbose=0
  613.  
  614. if pos('-QQ',astuff2)>0 then verbose=-1
  615.  
  616. replaceit=0
  617. if pos('-R',astuff2)>0 then replaceit=1
  618.  
  619. trunc8=0
  620. if pos('-8',astuff2)>0 then trunc8=1
  621.  
  622. if pos('-CHECK',astuff2)>0 then testsize=1
  623.  
  624. if pos('-NOCHECK',astuff2)>0 then testsize=0
  625.  
  626. dozip=0
  627. zz=pos('-ZIP',astuff2)
  628. if zz>0 then do
  629.     dozip=1
  630.     parse upper  var astuff2 . '-ZIP=' zipfile '.' .
  631.     if zipfile=' ' then do 
  632.         zipfile=date('n')
  633.         parse var zipfile a1 a2 a3
  634.         zipfile=a1||a2||right(a3,2)
  635.     end
  636.  
  637. /* check for ZIP.exe */
  638.     foo=doscommandfind('ZIP')
  639.     if foo='' then do
  640.         say "Sorry, can not find ZIP program in your OS/2 PATH. "
  641.         exit
  642.      end
  643.  
  644. end /* do */
  645. return 0
  646.  
  647. /***************/
  648. showhelp:
  649. parse arg iii
  650.   say
  651.    say " Available options are:"
  652.    say "            -Q =  quite mode "
  653.    say "            -R =  always replace "
  654.    say "            -8 =  copy to FAT style (8.3) file names "
  655.    say "        -CHECK =  check dest. drive for free space "
  656.    say "      -NOCHECK =  do NOT check dest. drive for free space "
  657.    say "      -ZIP=filename = store files in zip files on dest. drive"
  658.    if iii=0 then   say " Or, COPYDIR with no arguments to be prompted. "
  659. say
  660.    return 0
  661.  
  662.  
  663.  
  664.  
  665. /*************************************************/
  666. /* Check for the existence of a directory. Correctly identifies
  667.    empty directories.
  668. Usage:
  669.    flag=dir_exists(a_directory)
  670. where
  671.    flag=1 if a_directory exists (it might be an empty directory )
  672.    flag=0 if it doesn't exist
  673. */
  674. dir_exists:procedure 
  675. parse arg adir
  676.  
  677. adir=strip(adir)
  678. adir=strip(adir,'t','\')
  679. nowdir=directory()
  680. nowdrive=filespec('d',nowdir'\')
  681. nowpath=filespec('p',nowdir'\')
  682. adr=filespec('d',adir)
  683. if adr='' then do
  684.    if abbrev(adir,'\')=0 then 
  685.        adir=nowdrive||nowpath||adir
  686.    else
  687.        adir=nowdrive||adir
  688. end /* do */
  689.  
  690. foo=sysfiletree(adir,goo,'D')
  691. if  goo.0>0  then return 1
  692. return 0
  693.  
  694.  
  695.  
  696.