/bin/bash script to collect documentation--please debug/refine

/bin/bash script to collect documentation--please debug/refine

Post by Amy A. Lewi » Thu, 08 Jun 1995 04:00:00



Hmm.
I'm not certain that I should post this here, but if not, please turn the
flamethrowers on 'medium'.  The following is a bash script I wrote, because I
wanted to read the various documentation files in the /usr/src/linux hierarchy,
but I kept getting lost.  It works other places, too, of course; I've been
installing stuff and found it useful for extracting the readable info from a
new package.

I'm posting it for two reasons: 1) someone else may find it mildly useful, and
2) I very much hope that some guru or gurus will point out where it can be
refined and debugged (it seems to run perfectly for me, but I didn't exactly
test it to destruction).  It is a *bash* script, because I don't want to even
try to do the same thing without using some of bash's special builtins.

Note that it should be in the path.  Although, come to think of it, changing
one line might fix that. ($(echo $0) instead of readyou where it calls itself
recursively).  It also should be executable (you might could . it, I guess).

Comments, as I said, would be very welcome.

(about 200 lines follow--it looks like a few have wrapped; sorry)

#!/bin/bash
# readyou version 0.1
# readyou - a utility to locate the documentation files in a source tree
# and organize them in one place for easy reading.
# copyright 1995 Amy A. Lewis

# part one: parse the command line
# Another option to add: --diagnostics (-D?), which will explain what codes
# are assigned when we exit sloppily.

if [ "$readyousl" = "" ] ; then
  export readyousl=$SHLVL
  export incex=1
  export incmake=1
  sdir=.
  ddir=$HOME"/srcdoc"
  export ohshutup=1
  export exts=' .c .h .in .o .orig .S .sh .shar .tar .tar.gz .tgz '
# Make sure that there's a leading and a trailing space, or the first/last
# test will fail!  (Why?  I dunno)
  usage="
`basename $0` [-s source directory] [-d destination directory] [-D
--diagnostics
]
        [-h --help] [--version] [-q --quiet] [-x] [-m] [-[+]e
ext[,.ext[,...]]]

If source directory is omitted, `basename $0` uses the current directory.
If destination directory is omitted, `basename $0` uses \$HOME/srcdoc.
-x includes executables, which are excluded by default.
-m includes 'Makefile's, which are excluded by default.
The -e parameter defines the extensions to exclude.  It must be *last*.
If the option '+' is included, the extensions are added to the default list.
To see the default list, use -e alone.  Note that the extensions must include
the period ('.') and must be separated by commas without white space.

All options must be separated by white space (-m -x is defined, -mx is not;
-s /src/dir is defined, -s/src/dir is not).
"
  diag="
$(basename $0) returns 0 on a normal exit (this includes --help, --version, and
--diagnostics, and -e without a following extension, which are 'normal' exits).
  1: Source directory unreadable, not specified, or nonexistent.
  2: Destination directory unwritable, not specified, or nonexistent.
  3: Required utilities not present.
"
fi
# we have to have certain utilities, or things will fail miserably.
# To do this, we use the bash builtin "type -type [name]" and we tell the
# user that there's a problem, and quit, if the return is anything but "file"
# we quit with a nasty little note.  This is on the theory that
# the existence of an alias with the same name as a common program
# does not guarantee that the alias (or function) does the same thing.
# We need to have the following utilities: mkdir, cp, dirname, basename, sed.
# Do these tests even before parsing the command line, since we need sed and
# mkdir, at least, for them.

if [ $readyousl = $SHLVL ] ; then
  for i in {mkdir,cp,dirname,basename,sed} ; do
    if [ `type -type "$i"` != 'file' ] ;  then
      echo -n "$i is required to run this script, but does not exist or is an "
      echo "alias or function--exiting." >&2
      exit 3
    fi
  done
fi

while [ $# -ne 0 ] ; do
  case "$1" in
    -h | --help) echo "Usage: $usage" >&2 ; exit 0 ;;
    --version) echo "readyou v. 0.1 -- (c) 1995 Amy Lewis" >&2 ; exit 0 ;;
    -d)
      shift
      if [ $# -eq 0 ] ; then
        echo "You must specify a directory with -d!" >&2
        exit 2
      fi
      ddir=$1
      shift ;;
    -D | --diagnostics)
      echo "Diagnostics: $diag"
      exit 0 ;;
    -e)
      shift
      if [ $# -eq 0 ] ; then
        echo "Default extensions:$exts" >&2
        echo "Use $(basename $0) -e .ext1,.ext2,.ext3,... to override
defaults."
 >&2
        echo "Use $(basename $0) -+e .ext1,.ext2,.ext3,... to add to defaults."

>&2

        exit 0
      else
        export exts=" $(echo $1 | sed -e 's/,/ /g') "
      fi
      shift ;;
    -+e)
      shift
      if [ $# -ne 0 ] ; then
        export exts="$exts $(echo $1 | sed -e 's/,/ /g') "
        echo "$exts"
        shift
      fi ;;
    -m)
      export incmake=0
      shift ;;
    -s)
      shift
      if [ $# -eq 0 ] ; then
        echo "You must specify a directory with -s!" >&2
        exit 1
      fi
      sdir=$1
      shift ;;
    -q | --quiet)
      export ohshutup=0
      echo "Quiet!" >&2
      shift ;;
    -x)
      export incex=0
      shift ;;
    *) echo "Usage: $usage" >&2 ; exit 0 ;;
  esac
done

# Make sure the directories exist, and are readable/writable

if [ $readyousl -eq $SHLVL ] ; then
  if [ ! -d $ddir ] ; then
    if [ -e $ddir ] ; then
      echo "$ddir already exists, and is not a directory.  Exiting." >&2
      exit 2
    fi
    mkdir -p $ddir
    pushd $ddir >/dev/null
    ddir=`echo $PWD`
    popd >/dev/null
  elif [ ! -w $ddir ] ; then
    echo "You don't have write permission for $ddir.  Exiting." >&2
    exit 2
  else
    pushd $ddir >/dev/null
    ddir=`echo $PWD`
    popd >/dev/null
  fi
  if [ ! -d $sdir ] ; then
    echo "$sdir does not exist, or is not a directory.  Exiting." >&2
    exit 1
  elif [ ! -r $sdir ]  ; then
    echo "You don't have read permission for $sdir.  Exiting." >&2
    exit 1
  fi
fi

# Now we actually get to the meat of the script.
# First, make certain that our $sdir holds something useful (it might have ".")
cd $sdir
sdir=`echo $PWD`
if [ $ohshutup -ne 0 ] ; then echo "Entering $sdir." ; fi
if [ $readyousl -eq $SHLVL ] ; then
  if [ $ohshutup -ne 0 ] ; then echo "Destination directory: $ddir" ; fi
fi

# Hmm.  We need to name our files intelligibly.  But we don't want them
# to include the full path.
if [ $readyousl -eq $SHLVL ] ; then
  bname=`basename $sdir`
else
  cnt=$SHLVL
  fqdirn=$sdir
  bname=""
  while [ $cnt -ne $readyousl ] ; do
    bname="/"`basename $fqdirn`$bname
    fqdirn=`dirname $fqdirn`
    let $((cnt = cnt - 1))
  done
  bname=$(echo $bname | sed -e 's,/,.,g')
  bname=${bname#.}
fi
# and add a trailing period
bname=$bname"."

# Note that if you use this script in / , the above will still give hidden
# files.  Using "readyou -s .." won't, though.

nodirfiles=0
for fn in * ; do
  if [ -d $fn ] ; then
    if [ -r $fn ] ; then
      readyou -s $sdir"/"$fn -d $ddir
    else
      echo "You don't have read permission for $fn, sorry.  Skipping ..." >&2
    fi
# if -e exists, pass it along too, of course.  That's for later
  elif [ -f $fn ] ; then
    fqfn=$sdir"/"$fn
    resext=1
    if [ $incmake = 1 ] && [ "$fn" = "Makefile" ] ; then resext=0 ; fi
    if [ $incex = 1 ] && [ -x $fn ] ; then resext=0 ; fi
    dn=`dirname $fqfn`
#    for re in {.c,.h,.in,.o,.orig,.S,.sh,.shar,.tar,.tar.gz,.tgz} ; do
    for re in {$exts} ; do
      if [ $resext = 1 ] ; then
        bn=`basename $fqfn $re`
        cf=$dn"/"$bn$re
        if [ "$cf" = "$fqfn" ] ; then resext=0 ; fi
      fi
    done
    if [ $resext = 1 ] ; then
      cp $fn $ddir"/"$bname$fn
      if [ $ohshutup -ne 0 ] ; then echo "Copying $fn to $ddir/$bname$fn" ; fi
      let $((nodirfiles = nodirfiles + 1))
    fi
  else
    echo "$fn is not a directory or a regular file, skipping ..." >&2
  fi
done
echo "Exiting $sdir.  $nodirfiles files copied.
"

 
 
 

1. #!/bin/bash vs #!/usr/bin/env bash

(1) Which one of the two is better and why?

    #!/bin/bash

    #!/usr/bin/env bash

    Isn't the second more portable? Why then is it not seen so often?

(2) What exactly do these two do? Is there any difference between them?

(3) Why can't we simply replace the sha-bang line with something like
    the follwing?

    #!`which bash`

    Thanks in advance!

2. Dial Up PPP Server.

3. Moving /usr/local/bin/bash to /bin/bash

4. Creating a Linux CD from an FTP download

5. BASH BASH BASH BASH BASH BASH BASH BASH BASH BASH

6. HELP! - newbie

7. Debugging a Bash Shell Script

8. Slackware and kernel Upgrade > 2.0.0 trouble

9. /bin/sh -> /usr/local/bin/bash won't boot

10. The BASH shell and cgi-bin scripts

11. Debugging bash scripts?

12. ./bin/ba 2 /bin/bash??

13. Debugging bash scripts?