Lately I wanted to search for a Linux Command.
I didn’t knew the exact command, only that there must be a “wacom” in it. A
configuration tool to set some more details of my wacom tablet. So I thought.
Hey, just collect all binary files in all the directores in the PATH Environment
of Linux. The Path environment is divided with colons. Just let me give it a
Regex it can match against.
During development I realized that there can be multiple overlapping binaries
in different folders with the same name. Usually that makes sense as only the
first binary that is found is executed. This way you can control with PATH
which command you wanna override.
Here is my solution.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
#!/usr/bin/env perl
use v5.36;
use open ':std', ':encoding(UTF-8)';
use Data::Printer;
use Getopt::Long::Descriptive;
use List::Util qw/uniqstr/;
use Path::Tiny;
my ($opt, $usage) = describe_options(
'Usage: search_command REGEX [--full]',
['full|f', 'Print Full Paths', {default => 0}],
['help|h', 'Print this message', {shortcircuit => 1}],
);
print($usage->text) && exit if $opt->help;
print($usage->text) && exit if not defined $ARGV[0];
# Precompile regex
# - This way program aborts when regex is mailformed instead of continuing
# - and running the program
my $search = qr/$ARGV[0]/i;
# Get all binaries in PATH that match passed Regex
my @binaries =
sort { $a->[1] cmp $b->[1] } # Sort by basename
map { [$_, $_->basename] } # Schwartzian Transformation
grep { $_->is_file && $_->stat->mode & 0111 } # only files and executables
map { path($_)->children($search) } # get children of every PATH that match $search regex
split /:/, $ENV{PATH}; # split PATH on :
# prints full-path, usually useful when command exists multiple times
if ( $opt->full ) {
say $_->[0] for @binaries;
}
# by default - only print basename of binaries (single-time)
else {
say for uniqstr map { $_->[1] } @binaries;
}
=pod
=head1 search_command
Searches for a command in your PATH Environment by giving it a REGEX. Its useful
when you don't know the exact command but parts of it. REGEX is case-insensitive
by default.
=head1 EXAMPLES
=begin text
$ search_command wayland
Xwayland
es2gears_wayland
es2gears_wayland.x86_64-linux-gnu
wayland-scanner
$ search_command wacom
xsetwacom
$ search_command wacom --full
/usr/bin/xsetwacom
/bin/xsetwacom
=end text
|