]>
Commit | Line | Data |
---|---|---|
ccc6cda3 JA |
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 |