Imported from ../bash-2.0.tar.gz.
[platform/upstream/bash.git] / examples / scripts.v2 / where
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
15 name=${0##*/}
16 Usage="Usage: $name [-hx] 'pattern' ..."
17 typeset -i exact=0
18
19 phelp()
20 {
21 echo "$name: find executable files in PATH that match patterns.
22 $Usage
23 $name searches each directory specified in the PATH environment variable
24 for executable files that match the specified patterns.  Patterns are
25 given as Korn shell filename patterns.  They are surrounded by implicit
26 '*' characters, so that \"foo\" will match any executble file whose name
27 contains contains \"foo\".  This can be overridden by using '^' and '$' to
28 force a match to start at the beginning and end at the end of a filename
29 respectively.  Characters that are special to the shell must generally
30 be protected from the shell by surrounding them with quotes.
31 Examples:
32 $name foo
33 lists all executable files in PATH that contain foo.
34 $name '^b*sh$'
35 lists all executable files in PATH that start with b and end with sh.
36 An error message is printed if a no matching file is found for a pattern.
37 Options:
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
43 istrue()
44 {
45         test 0 -ne "$1"
46 }
47
48 isfalse()
49 {
50         test 0 -eq "$1"
51 }
52
53 while 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
59 done
60
61 shift $((OPTIND-1))
62
63 set +f                  # make sure filename globbing is on
64 Args=("$@")             # save args
65
66 OIFS=$IFS
67 IFS=:           # Make PATH be split on :
68 Paths=($PATH)
69 IFS=$OIFS
70
71 for 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
111 done