#!/bin/sh # @(#) /u/des/src/lst/lst 1.4 01/07/29 12:57:30 # lst -- ls specified file types (those recognized by `find') in # specified directories # # returns 0 for no errors and at least one match found in each dir argument; # returns 1 if any errors, else 2 if any dirs with no matches; # # 12/98, D.Singer PROG=`basename "$0"` USAGE="Usage: $PROG [-bcdDflps] [--h[elp]] [--l[ong]] [--o[ne]] [--] [dir...]" # and see help message below DFLT_TYPE='f' TYPES= HELP= LONG= ONE= STATUS=0 # exit status # # environment variables # : ${LST_SPACE=' '} # space to use with --o SYNTAX="$PROG: option syntax error." # # platform specific settings # SYS="`uname -sr`" # OS type case "$SYS" in "SunOS "*) AWK="nawk" ;; *) AWK="awk" esac # # do echo with newline suppression # _C= _N= _NC= echon() { if [ ! "$_NC" ]; then if [ "/`echo '\c'`" = '/' ]; then _C='\c' elif [ "/`echo -n`" = '/' ]; then _N='-n ' else : # unknown fi _NC=1 fi echo $_N"$*$_C" } syntax_error() { echo "$SYNTAX" >&2 echo "$USAGE" >&2 exit 1 } #arg_syntax_check() { # [ "$1" -lt 1 ] && syntax_error #} # # process command line options and arguments # while [ $# != 0 ]; do case "$1" in # options without argument -b) TYPES="$TYPES b" ;; -c) TYPES="$TYPES c" ;; -d) TYPES="$TYPES d" ;; -D) TYPES="$TYPES D" ;; -f) TYPES="$TYPES f" ;; -l) TYPES="$TYPES l" ;; -p) TYPES="$TYPES p" ;; -s) TYPES="$TYPES s" ;; --h|--help) HELP=1 ;; --l|--long) LONG=1 ;; --o|--one) ONE=1 ;; # options with argument # -c) # shift # arg_syntax_check "$#" # CARG="$1" # CFLAG=1 # ;; # ... --) shift break ;; # unknown option -?) syntax_error ;; # compound option -??*) # break up a compound option NEW_OPTS=`$AWK 'BEGIN { OPT_STR = "'"$1"'"; LEN = length(OPT_STR); NEW_OPTS = ""; STATUS = 0; for (POS=2; POS+0 <= LEN; ++POS) { OPT = substr(OPT_STR,POS,1); if (OPT !~ /[a-zA-Z0-9_]/) STATUS = 1; NEW_OPTS = NEW_OPTS " -" OPT; } print NEW_OPTS; exit STATUS; }' <&-` || { syntax_error } shift set -- $NEW_OPTS ${1:+"$@"} continue ;; # end of options, just command arguments left *) break esac shift done if [ "$HELP" ]; then echo " $PROG: For each directory argument, list only the objects that match any of the selected types. $USAGE -b block-special files -c character-special files -d directories -D doors -f regular files (default) -l symbolic links -p named pipes -s sockets --h (or --help) print this help and exit --l (or --long) long listing --o (or --one) list all matches in one line dir directory to search, default is current directory The environment variable \"LST_SPACE\" can be used to set the space character(s) for the --o option. " exit 0 fi # # use the default type if no type selected # [ -z "$TYPES" ] && TYPES="$DFLT_TYPE" # # look for mutually exclusive options # if [ "$LONG" -a "$ONE" ]; then echo "$PROG: cannot use \"--l\" and \"--o\" together." >&2 echo "$USAGE" >&2 exit 1 fi # # construct part of the 'find' expr # for TYPE in $TYPES; do [ -n "$TYPES_EXPR" ] && TYPES_EXPR="$TYPES_EXPR -o " TYPES_EXPR="${TYPES_EXPR}-type $TYPE" done #echo "TYPES_EXPR=\"$TYPES_EXPR\"" #exit # # set the default directory, if necessary # if [ $# = 0 ]; then # if no command line args, use the current directory set -f set -- '.' set +f fi NUM_DIRS=$# # # get the starting point # if [ $# -gt 1 ]; then START_DIR=`pwd` || { echo "$PROG: cannot determine current directory." >&2 exit 1 } fi # # process each directory # for DIR do # more verbose if multiple directories [ "$NUM_DIRS" != 1 ] && echo "$DIR:" [ -d "$DIR" ] || { echo "$PROG: \"$DIR\" not a directory." >&2 [ $# -gt 1 ] && echo STATUS=1 shift continue } [ -r "$DIR" ] || { echo "$PROG: directory \"$DIR\" not readable." >&2 [ $# -gt 1 ] && echo STATUS=1 shift continue } [ -x "$DIR" ] || { echo "$PROG: cannot chdir to directory \"$DIR\"." >&2 [ $# -gt 1 ] && echo STATUS=1 shift continue } cd "$DIR" # # get names of files with the selected type, skipping "." entry # NAMES=`find "." -name "." -o \( \( \( $TYPES_EXPR \) -print -prune \) -o -prune \) | # # get rid of path part, and sort entries # $AWK '{ sub(".*/",""); print; }' | sort ` #echo "NAMES=\"$NAMES\"" #exit # # output the names, or the long listings if selected # if [ -z "$NAMES" ]; then # status for any dirs with no matches [ "$STATUS" = 0 ] && STATUS=2 else if [ "$LONG" ]; then _IFS="$IFS" IFS=' ' ls -ld `echo "$NAMES"` IFS="$_IFS" elif [ "$ONE" ]; then _IFS="$IFS" IFS=' ' SPACE= for NAME in $NAMES; do echon "$SPACE$NAME" SPACE="$LST_SPACE" done [ "$SPACE" ] && echo IFS="$_IFS" else echo "$NAMES" fi fi if [ $# -gt 1 ]; then # # get back to the starting point so that directories # resolve correctly # cd "$START_DIR" # # more multiple directory verboseness # echo "" fi shift done exit $STATUS