% findcmd foo foo_bar #### % findcmd grep zgrep grep egrep cgrep fgrep #### #!/usr/bin/env perl use warnings; use strict; use Getopt::Long; use Pod::Usage; my $print_path; my $re; parse_args(); my @dirs = split /:/, $ENV{PATH}; for my $dirname (@dirs) { if (-d $dirname) { if (opendir my $DIR, $dirname) { my @xfiles = grep { -x "$dirname/$_" } # choose only executable files grep { !-d "$dirname/$_" } # reject directories grep { /$re/ } # pattern match readdir $DIR; closedir $DIR; for (@xfiles) { if ($print_path) { print "$dirname/$_\n"; } else { print "$_\n"; } } } } } exit; sub parse_args { my ($help, $sens); GetOptions( 'sens' => \$sens, 'path' => \$print_path, 'help' => \$help ) or pod2usage(); $help and pod2usage(-verbose => 2); if (@ARGV) { my $pat = shift @ARGV; $re = ($sens) ? qr/$pat/ : qr/$pat/i; } else { pod2usage('Error: regex required.'); } @ARGV and pod2usage("Error: unexpected args: @ARGV"); } =head1 NAME findcmd =head1 SYNOPSIS findcmd [options] regex Options: -help Verbose help -path Print out full directory paths also -sens Case-sensitive [default is case-insensitive] =head1 DESCRIPTION Search through the directories in the Unix PATH variable for executable files matching a specified regular expression. The names of all the commands which match will be printed to STDOUT. This is based on the I script from the CD that comes with the I book. It is important to note that neither aliases nor shell built-ins (I, I, etc.) will be printed since neither is found in directories in the PATH variable. Any directories listed in the PATH variable which do not exist or are not readable will be silently ignored. Duplicate directories will not be removed. =head1 ARGUMENTS =over 4 =item regex A regular expression is required. The regex may be a simple string, such as C, or it may be a more complicated expression, such as C<^foo.*bar\d>. The regex syntax is Perl; it should not be confused with shell wilcard syntax or the syntax for other common Unix utilities, such as I or I. It is best to quote the regex to prevent interaction with the shell. =back =head1 OPTIONS All options can be abbreviated. =over 4 =item sens By default, the regular expression is case-insensitive. So, if the input regex is C, it will match C as well as C and C, etc. To use case-sensitive, use the C<-sens> option. findcmd -sens foo =item path By default, only the command name is printed. To instead print the full directory path to the command, use the C<-path> option. findcmd -path foo =item help Show this verbose usage information. =back =head1 EXAMPLES Match a command name exactly (C), and print the full directory path. This provides the same functionality as the I utility from I. findcmd -sens -path '^gnuplot$' Find all executable files in all path directories: findcmd . Find commands which begin with a dot: findcmd '^\.' Find commands with strange characters (not word, period, plus, dash): findcmd '[^\w.+-]' Find commands with a literal, case-sensitive "-s": findcmd -sens '\-s' =head1 SEE ALSO Refer to the following book: Unix Power Tools 2nd Edition Jerry Peek, Tim O'Reilly and Mike Loukides O'Reilly & Associates, Inc. =cut