1#! /bin/bash
2#
3# original from:
4# @(#) where.ksh 1.1 94/07/11
5# 91/01/12 john h. dubois iii (john@armory.com)
6# 92/08/10 Only print executable *files*.
7# 92/10/06 Print err msg if no match found.
8# 92/11/27 Added implicit *
9# 93/07/23 Print help only if -h is given.
10# 94/01/01 Added -x option
11# 94/07/11 Don't bother with eval
12#
13# conversion to bash v2 syntax done by Chet Ramey
14
15name=${0##*/}
16Usage="Usage: $name [-hx] 'pattern' ..."
17typeset -i exact=0
18
19phelp()
20{
21echo "$name: find executable files in PATH that match patterns.
22$Usage
23$name searches each directory specified in the PATH environment variable
24for executable files that match the specified patterns.  Patterns are
25given as Korn shell filename patterns.  They are surrounded by implicit
26'*' characters, so that \"foo\" will match any executble file whose name
27contains contains \"foo\".  This can be overridden by using '^' and '$' to
28force a match to start at the beginning and end at the end of a filename
29respectively.  Characters that are special to the shell must generally
30be protected from the shell by surrounding them with quotes.
31Examples:
32$name foo
33lists all executable files in PATH that contain foo.
34$name '^b*sh$'
35lists all executable files in PATH that start with b and end with sh.
36An error message is printed if a no matching file is found for a pattern.
37Options:
38-h: Print this help.
39-x: Find exact matches only; equivalent to putting ^ and $ at the start
40    and end of each pattern."
41}
42
43istrue()
44{
45	test 0 -ne "$1"
46}
47
48isfalse()
49{
50	test 0 -eq "$1"
51}
52
53while getopts "xh" opt; do
54	case "$opt" in
55	x)	exact=1;;
56	h)	phelp ; exit 0;;
57	*)	echo -e "$Usage\nUse -h for help." 1>&2; exit 2;;
58	esac
59done
60
61shift $((OPTIND-1))
62
63set +f			# make sure filename globbing is on
64Args=("$@")		# save args
65
66OIFS=$IFS
67IFS=:		# Make PATH be split on :
68Paths=($PATH)
69IFS=$OIFS
70
71for arg in "${Args[@]}"; do
72
73    # get rid of leading ^
74    if istrue $exact; then
75	arg=${arg}
76    else
77	    case "$arg" in
78	    ^*)	arg=${arg#?};;
79	    *) arg="*$arg" ;;	# Pattern is not anchored at start
80	    esac
81    fi
82
83    # get rid of trailing $
84    if istrue $exact; then
85	arg="$arg"
86    else
87	case "$arg" in
88	*\$)	arg=${arg%?} ;;
89	*)	arg="$arg*" ;;
90	esac
91    fi
92
93    found=0	# Pattern not found yet
94    Patterns=
95    # Make a pattern for each element of PATH
96    for PathElem in "${Paths[@]}"; do
97	[ -z "$PathElem" ] && PathElem=.
98	Patterns="$Patterns $PathElem/$arg"
99    done
100
101    # Find all pattern matches that are executable regular files.
102    for file in $Patterns; do
103	if [ -x "$file" ] && [ -f "$file" ]; then
104	    echo "$file"
105	    found=1
106	fi
107    done
108    if [ $found = 0 ]; then
109	echo "$arg: not found." 1>&2
110    fi
111done
112