#!/bin/bash ## WH 1998 FEB 19, 2001 Jan 15 ## This is a variant on ksh's "whence -p" and "type"=whence -v and csh's "which". ## This variant lists **all** files in $PATH that match a file **pattern**. ## Utility "find" is not really appropriate for this. ## Using full path names below to guard against bad PATH. ## Using bash instead of sh, since sh does not handle empty argument ## list to "set" correctly. usage() { echo >&2 "Usage: ${0##*/} [-m] [-s] [-p ] [--] 'blank-free file pattern'" /bin/cat >&2 <<\EOF Find all files on PATH (in same order) matching the file pattern. Use ' quotes to protect the pattern if it contains wildcards. -p : Use the colon separated list of directories instead of PATH -m: Search for manual entries by using MANPATH instead of PATH and treating the pattern as man*/pattern.* -s: Use a sane internal setting for PATH and MANPATH --: Use this option if pattern starts with a - EOF exit 1 } man=no sane=no path="$PATH" while getopts :msp: opt do case $opt in m) man=yes path="$MANPATH" ;; s) sane=yes ;; p) path="$OPTARG" ;; \?|:) echo >&2 "Error: Bad option $OPTARG or missing argument." usage ;; *) usage ;; esac done shift $(( OPTIND - 1 )) if [ $sane = yes ] ; then if [[ $man = yes ]] ; then path=/usr/man:/usr/local/man else path=/usr/bin:$HOME/bin:/usr/local/bin:. fi fi if [ $# != 1 ] ; then usage fi ## set pattern if [ $man = no ] ; then pattern="$1" else pattern="man*/$1.*" fi ## Set arguments to be the path components with colons removed. ## However, PATH=:/bin::/: means PATH=.:/bin:.:/:. so the first three ## sed replacements just put these implicit periods back in. ## If PATH=:/bin::/: then $1 to $5 will be set to: . /bin . / . export path set -- `/bin/echo $path | /bin/sed -e 's/^:/.:/g' -e 's/:$/:./g' -e 's/::/:.:/g' -e 's/:/ /g'` ## list files matching pattern for dir do /bin/ls -1d $dir/$pattern 2>/dev/null ## suppress error "no file matches" done exit 0