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
|
---|