Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!


Click here to return to the 'Describe all Unix apps in current PATH' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Describe all Unix apps in current PATH
Authored by: merlyn on Jan 09, '07 08:12:16AM
You know, I hear people say how ugly Perl is, but let's compare the Perl equivalent to the massively messy thing just posted:

#!/usr/bin/env perl
use strict;
$|++;

my %commands;
for my $dir (split /:/, $ENV{PATH}) {
  next unless opendir DIR, $dir;
  for my $command (readdir DIR) {
    $commands{$command}++ if -f "$dir/$command" and -x _;
  }
}

for my $command (sort keys %commands) {
  for (`whatis $command`) {
    my ($key, $detail) = split /\s+- / or next;
    next unless $key =~ s/\((1|1m|6|8)\)//g;
    printf "%20s - %s", $key, $detail;
  }
}
Not only that, but it probably runs hella faster. :)

[ Reply to This | # ]
Describe all Unix apps in current PATH
Authored by: merlyn on Jan 09, '07 08:15:43AM
Oh wait, that's not hella faster, because it still invokes whatis repeatedly (and with a whitespace problem). This is hella faster:

#!/usr/bin/env perl
use strict;
$|++;

my %commands;
for my $dir (split /:/, $ENV{PATH}) {
  next unless opendir DIR, $dir;
  for my $command (readdir DIR) {
    $commands{$command}++ if -f "$dir/$command" and -x _;
  }
}

open WHATIS, "-|", "whatis", sort keys %commands or die;
while (<WHATIS>) {
  my ($key, $detail) = split /\s+- / or next;
  next unless $key =~ s/\((1|1m|6|8)\)//g;
  printf "%20s - %s", $key, $detail;
}


[ Reply to This | # ]
Describe all Unix apps in current PATH
Authored by: gshenaut on Jan 09, '07 08:57:51AM
Well, formatting helps a little:
echo $PATH \
| sed -e 's/:/ /g' \
| xargs -J % find % -maxdepth 1 \( -type f -or -type l \) \
| xargs basename | sort | uniq \
| xargs whatis 2> /dev/null \
| grep -E '\((1|1m|6|8)\)' \
| perl -ne '($name, $descrip) = m/^(.*?)\s+- (.*)$/; $name =~ s/\((1|1m|6|8)\)//g; printf("%-20s - %s\n", $name, $descrip)'
Greg Shenaut

[ Reply to This | # ]
Sorry, bash wins.
Authored by: bm on Jan 25, '07 11:46:07PM
merlyn:
That's not faster at all. Even with an added command in bash (see below), 'time' reports:
  bash
real    0m44.014s
user    0m11.898s
sys     0m25.316s

  perl
real    0m55.462s
user    0m0.302s
sys     0m0.172s
One caveat: that's bash 3.2.9 -- the latest, while perl remains at 5.8.7;
..the bash-code used an additional 'sed' to escape whitespacing in $PATH.

[ Reply to This | # ]
pedagogy
Authored by: hayne on Jan 09, '07 10:57:04AM

As a tool to produce the list of commands with descriptions, a pure Perl solution is obviously better. And that's probably how I would have done it had I started out to produce such a tool. But this complicated pipeline of commands started off life in a discussion about getting a list of commands in your PATH (with no descriptions) and grew from there.

I thought it was valuable pedagogically to leave it as a pipeline since that way readers can experiment (in the way I mentioned at the end of the article) to see what results with different commands.
This sort of experimentation would be less likely had I just presented a Perl script.

I think for many readers, the idea of a pipeline of commands and the explanations of the pipeline stages may be more valuable than the end tool.



[ Reply to This | # ]
pedagogy
Authored by: ccjensen on May 21, '08 08:00:53AM

I know this is 'old' news, but thanks for the script and BRILLIANT explanation of each step. I am revising for an exam which will require us to write pipelines, and this was most helpful!



[ Reply to This | # ]