PARM dir=!hpcwd filter=100 entry=main
#
# This script traverses "dir" and counts the number of file/dir objects under
# "dir". This counting is recursive for all directories under "dir".
#  Syntax: filecnt dir-name [filter]
#   "dir" must be in HFS syntax, so the SYS account is /SYS, wildcard allowed.
#   "filter" causes this script to omit displaying directories containing less
#            than "filter" objects.
# Note: lots of unnecessary complexity is due to the fact that FINFO (and listf
# too!) does not return the 'eof' for an account, group or directory. So we
# use listfile for a horizontal cut at one level below the "dir" parm, and
# then listfile again to traverse sub-dirs below that level.
# Note: this is the "all script, no program" version of FILECNT.  FILECNT2
#       runs a simple program for each recursive iteration to solve the pre-
#       7.0 problem of a nesting limit of 30 deep.
#
# Author:  Jeff Vance, HP-CSY, June '02

if "!entry" = "main" then
   setvar _fc_vers "A.01"
   echo
   echo     ** File Counter version !_fc_vers **
   echo
   if "!dir" = "?" then
echo ![basename(hpfile)] is designed to traverse the entire directory &
     structure under the
echo "DIR" parm, counting the number of files and sub-directories (objects).
echo
echo    Syntax:  ![basename(hpfile)] DIR [filter]
echo
echo    - "DIR" parm must be specified in HFS/POSIX syntax, e.g. the SYS
echo    account becomes "/SYS".  Wildcards are supported for the DIR parm,
echo    e.g. "/[A-G]@".  The default DIR is your Current Working Directory.
echo
echo    - "FILTER" is optional and defaults to 100.  Directories containing
echo    fewer than FILTER objects are not displayed to $stdlist.
echo
echo    A summary of the number of files/dirs counted and the directory with
echo    the most files is shown last.
echo
      return
   endif

   setvar _fc_tot_fcnt   0
   setvar _fc_most       0
   setvar _fc_most_dir   ""
   setvar _fc_fecho_cnt  0
   setvar _fc_dir        "!dir"

   # enforce POSIX syntax in DIR parm
   if delimpos(_fc_dir,"/.") <> 1 then
      echo ** ERROR: account, group, dir names must be in HFS syntax
      return
   endif
   # remove trailing slash, if any
   if len(_fc_dir) > 1 and rht(_fc_dir,1) = "/" then
      setvar _fc_dir lft(_fc_dir,len(_fc_dir)-1)
   endif

   # create horizontal cut based on "dir" parm
   setvar hpcierr 0
   continue
   listfile !_fc_dir,6;notree >lfout1
   if hpcierr > 0 then
      echo ** listfile command failed...
      print lfout1
      return
   elseif hpcierr < 0 then
      echo No matches for directory parm "!dir"
      return
   endif

   # count files/dirs in horizontal cut and traverse all sub-dirs
   xeq !hpfile !_fc_dir !filter dirtraverse <lfout1
   if _fc_fecho_cnt = 0 then
      echo  ** All directories contain fewer than !filter objects.
      echo     Try using a smaller FILTER value.
   endif
   echo
   echo  !_fc_tot_fcnt objects examined with !_fc_fecho_cnt displayed. &
         Filter = !filter
   echo  Directory with most objects: !_fc_most_dir (!_fc_most)
   echo
   deletevar _fc_@

elseif "!entry" = "dirtraverse" then
   # Input redirected to listfile,6 in HFS output.
   # This routine counts the files in the horizontal cut from the main entry
   # and recursively counts objects in each sub-dir.
   #
   setvar _fc_eof finfo(hpstdin,'eof')
   while setvar(_fc_eof,_fc_eof-1) >= 0 do
      setvar _fc_dir ltrim(rtrim(input()))
      if rht(_fc_dir,1) = "/" then
         # have a directory to traverse...
         setvar hpcierr 0
         continue
         listfile !_fc_dir@,6 >lfout2
         if hpcierr = 0 then
            xeq !hpfile !_fc_dir !filter direxam <lfout2
         endif
      endif
   endwhile
   return

elseif "!entry" = "direxam" then
   # Input redirected to listfile,6 in HFS output.
   # This routine counts the files in each horizontal cut for all sub-dirs that
   # are traversed in the "dirtraverse" entry.  This routine is recursive and
   # thus the eof counters and temp files that hold the output of successive
   # listf's must be unique for each recursion level.  If the number of objects
   # at this level exceed the FILTER threshold then the dir name and file count
   # are written to $stdlist.  The dir containing the most objects is also
   # discovered here.
   #
   setvar _fc_eof_!hpusercmdepth finfo(hpstdin,'eof')
   setvar _fc_fcnt _fc_eof_!hpusercmdepth
   setvar _fc_tot_fcnt _fc_tot_fcnt+_fc_fcnt
   if _fc_fcnt >= !filter then
     echo ![rpt(" ",9-len("!_fc_fcnt"))] !_fc_fcnt objects in "!dir"
     setvar _fc_fecho_cnt _fc_fecho_cnt+1
   endif
   if _fc_fcnt > _fc_most then
     setvar _fc_most _fc_fcnt
     setvar _fc_most_dir "!dir"
   endif

   while setvar(_fc_eof_!hpusercmdepth,_fc_eof_!hpusercmdepth-1) >= 0 do
      setvar _fc_dir ltrim(rtrim(input()))
      if rht(_fc_dir,1) = "/" then
         # another dir so recurse again...
         setvar hpcierr 0
         continue
         listfile !_fc_dir@,6 >lf!hpusercmdepth
         if hpcierr = 0 then
            xeq !hpfile !_fc_dir !filter direxam <lf!hpusercmdepth
         endif
      endif
   endwhile
   return
endif