Skip to content

Instantly share code, notes, and snippets.

@jwodder
Created July 3, 2014 17:01
Show Gist options
  • Save jwodder/61bebc3ca55bf04ea4cc to your computer and use it in GitHub Desktop.
Save jwodder/61bebc3ca55bf04ea4cc to your computer and use it in GitHub Desktop.
Find binaries in the user's PATH
#!/usr/bin/perl -wl
# finbin - find binaries in the user's PATH
# See the POD at the end of the file for documentation.
use strict;
use File::Glob 'bsd_glob', 'GLOB_NOCASE', 'GLOB_QUOTE', 'GLOB_BRACE';
use Getopt::Std;
my %opts;
our $VERSION = 1.3;
getopts('fFp:qx', \%opts) || exit 2;
argLoop: for (@ARGV) {
for my $d (split /:/, $opts{p} || $ENV{PATH}) {
$d = '.' if $d eq '';
for (grep { !$opts{x} || -x } bsd_glob("$d/$_", GLOB_NOCASE | GLOB_QUOTE | GLOB_BRACE)) {
exit 0 if $opts{q};
print;
exit 0 if $opts{f};
next argLoop if $opts{F};
}
}
}
exit 1 if $opts{q};
sub HELP_MESSAGE {
select shift;
print <<EOT;
Usage: $0 [-F | -f | -q] [-x] [-p path] pattern ...
Type `perldoc finbin` for more information.
EOT
exit 0;
}
__END__
=pod
=head1 NAME
B<finbin> - find binaries in the user's PATH
=head1 SYNOPSIS
B<finbin> [B<-F> | B<-f> | B<-q>] [B<-x>] [B<-p> I<path>] I<pattern> ...
=head1 DESCRIPTION
B<finbin> searches the user's PATH for any files matching the given I<pattern>
and prints the results to standard output. It is intended as a replacement for
the inconsistently implemented L<which(1)> and L<whereis(1)> commands.
If B<finbin> is given more than one operand, it searches for each one
individually and prints out the results as it finds them. Each operand is
interpreted as a shell wildcard pattern to match against the contents of each
directory in the PATH. If no wildcards are present in an operand, it is
treated as the basename of a program to look for; if wildcards are present,
they may have to be escaped or quoted in order to avoid interpolation by one's
shell.
=head1 OPTIONS
=over
=item B<-F>
Print out only the first match found for each operand.
=item B<-f>
Exit immediately after finding the first match.
=item B<-p> I<path>
Use I<path> as the path to search rather than the user's PATH environment
variable. Directories in I<path> must be separated by colons. An empty string
in I<path> is interpreted as referring to the current directory.
=item B<-q>
Do not print anything; instead, exit with a status of 0 if any matches were
found, 1 otherwise.
=item B<-x>
Only find matches that the user has execute permission for.
=back
=head1 RESTRICTIONS
Due to Getopt::Std's parsing of all options at once, rather than parsing them
one at a time as L<getopt(3)> does, mutually exclusive options (i.e., B<-F>,
B<-f>, and B<-q>) that are given on the command line cannot be resolved by
seeing which comes last. Instead, a set of built-in precedences is used: B<-q>
overrides B<-f>, which overrides B<-F>.
Wildcard matching is implemented using Perl's C<File::Glob::bsd_glob> function,
which may or may not support whatever non-standard patterns you desire.
=head1 SEE ALSO
L<command(1)>, L<whereis(1)>, L<which(1)>
=head1 AUTHOR
John T. Wodder II <jwodder@sdf.lonestar.org>
=head1 LICENSE
Feel free to do whatever the Tartarus you want with this.
=head1 HISTORY
B<finbin> was originally written 2008 Oct 15 by John T. Wodder II. It was last
edited 2014 Jul 03 by John Wodder.
=cut
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment