#!/bin/bash # $Id: findcmd,v 1.1 2006/10/29 16:41:18 jpeek Exp $ # findcmd - find all files in PATH matching wildcard-type pattern # Usage: findcmd # This script is in the public domain. If you improve it, please # consider sending a copy to the author, Jerry Peek , # so he can share your fixes with others. # CONFIGURE: Don't match these Windows files unless name entered explicitly: GLOBIGNORE='*.dll:*.wsc' myname=${0##*/} # filename of this script (without leading path) # Be sure shell won't remove or complain about unmatched patterns: shopt -u failglob nullglob # Resolve any symbolic links in directory pathnames for $PWD, etc.: set -o physical # Patterns must be entered after script starts. This avoids "No match" # errors, errors caused by parent shell expanding patterns early, etc: if [ $# -ne 0 ] then echo "Usage: $myname" 1>&2 exit 1 fi # Copy valid directories from PATH list to pathdirs array. declare -a pathdirs OLDIFS="$IFS" IFS=: for dir in $PATH do # Convert "current directory" to its absolute pathname: case "$dir" in .|"") dir="$PWD" ;; esac if [ ! -d "$dir" ] then echo "$myname: warning: skipping invalid directory '$dir' in PATH" continue fi # If directory is already in pathdirs, skip it and resume outer loop: for member in "${pathdirs[@]}" do [ "$dir" == "$member" ] && continue 2 done # Else, assign dir to next element of pathdirs (this trick obtains # the next element thanks to the zero-based array indexes in bash): pathdirs[${#pathdirs[*]}]="$dir" done IFS="$OLDIFS" # End loop if "read" returns non-zero (for end-of-input) or $pat is empty: while echo -en "\n>>> $myname: Enter command name pattern (example: *cmd*). Empty line exits:\n> " read pat do test -z "$pat" && break for dir in "${pathdirs[@]}" do # Skip $dir if can't access (couldn't do this test when pathdirs # was set because it might change the meaning of . in PATH): cd "$dir" || continue # If pattern has * ? [], expand with "set", else use test -x. case "$pat" in *[][*?]*) # Expand pattern as it would be on a command line: set $pat # If pattern didn't expand, it will match itself; we skip it: if [ "$1" != "$pat" ] then # Loop through positional parameters set by "set $pat" above # and show full pathname of only the executable files: for match do test -x "$match" && echo "$dir/$match" done fi ;; *) # No wildcards in pattern. Test for exact match: [ -x "$pat" -a ! -d "$pat" ] && echo "$dir/$pat" ;; esac done done exit 0