Solved

Apropos for commands only?

Posted on 2009-05-12
26
626 Views
Last Modified: 2013-12-26
When I'm looking for commands to do an operation, I sometimes use apropos.  The problem is that apropos will list not just unix commands, but also C APIs as well.  There are plenty C APIs, and they easily outnumber commands listed.

My question:  is there a way to essentially do an apropos on commands only?

I'm not just trying to do a one line listing of commands (for example, if I wanted this for ls I'd do an "apropos '^ls('").  I am trying to get some kind of command or script that I can use that would accomplish searching the context of command descriptions as well, something I think apropos can be really good at.  Maybe I'm just forgetting or missing something really obvious here.

coder
0
Comment
Question by:coder1313514512456
  • 12
  • 6
  • 4
  • +3
26 Comments
 
LVL 76

Assisted Solution

by:arnold
arnold earned 370 total points
ID: 24370926
You could try running which "command".

This will based on your path return the command's location.
apropos is similar to man -k "command"
keyword search in the manual pages.
It returns all the references it has to address your query.

I'm not really sure what you are looking to do.

0
 
LVL 40

Expert Comment

by:omarfarid
ID: 24371161
apropos looks in an index of man pages, and I am not sure if that index can be rebuilt to include man pages of commands only. Look into man page of apropos and see if that is possible
0
 

Author Comment

by:coder1313514512456
ID: 24371179
arnold:

Essentially my point is that apropos is nice because it returns a list of descriptions and you can basically grep on those descriptions.  I still want to grep on those descriptions, but I just want results that are unix commands.  So I want any results that are from the API list.

Does that clarify my objective?
0
 

Author Comment

by:coder1313514512456
ID: 24371187
omarfarid:

Doesn't look like apropos man page really contains much of anything.  I suppose I could try to focus on rebuilding the man pages with only commands, but I'm not even sure how to begin going about to do this.  If memory serves, the man pages are interspersed with both unix command line commands and C APIs.  But I could certainly have that wrong.

0
 
LVL 40

Expert Comment

by:omarfarid
ID: 24371221
what flavor of unix do you have?
0
 
LVL 40

Assisted Solution

by:omarfarid
omarfarid earned 60 total points
ID: 24371228
I could think of filtering the results since apropos returns the section name along with the line and then you could pass it through grep to filter the other sections you don't want
0
 

Author Comment

by:coder1313514512456
ID: 24371446
(I'm looking for a general unix solution here, I've encountered it on enough flavors to be an annoyance.  But for examples sake, let's say darwin/os x.)

The thing with grepping on section names is that there are plenty of C APIs in all the sections, it appears.  Unless there's some kind of subsection or categorization I don't know about.  And there's certainly plenty I don't know about.

0
 
LVL 84

Assisted Solution

by:ozo
ozo earned 20 total points
ID: 24371695
you could grep the output for  '(1)'
0
 
LVL 61

Expert Comment

by:gheist
ID: 24374360
exactly like you said:
| grep '(1)'
0
 
LVL 76

Accepted Solution

by:
arnold earned 370 total points
ID: 24374532
Well if you are using grep/script.
You can first grep for items that match your needs.
You can then pass that first item in the response which is either a command or a C/C++ etc. function.
Run a which name.  IF it is in the path, it is a command print out the line , other wise go to the next skip it.

Basically you create a script that uses apropos to get responses and then using the responses faret out

#!/bin/bash
 

if [ -z "$1" ]; then # check to make sure they provided what to search for

echo "Usage: $0 keyword"

exit

fi

apropos $1 | while read a; do

#set will declare the space separated items starting from $1 ->$n items 

set $a 

which $1 2>/dev/null >/dev/null

if [  "$?" -eq "0" ] ; then # check that this is an existing command using the status of the execution of the which command. 

echo "$a"

done

Open in new window

0
 
LVL 40

Assisted Solution

by:omarfarid
omarfarid earned 60 total points
ID: 24375285
I have solaris and linux and both shows section 1 for user commands and section 8 for admin commands

try to put this in a script file and make it executable (and may be in your bin dir)

apropos $1 | egrep '(1)|(8)'

you can run it as

myscript word
0
 

Author Comment

by:coder1313514512456
ID: 24381636
ozo, gheist, omarfarid:  Although (1) and (8) do appear for commands, the problem is that they don't filter the other way, that is, they also contain C APIs and I'd be stuck with my same problem (although quite diminished, so thanks!)
arnold:  THAT looks like a really, really, good idea.  I can't try it out right now but by first blush it looks like you may just have solved my problem.  Of course!   Which it, and if it doesn't which, it's not a command.  Brilliant.
I'll get back to you geniuses.  Thanks again everybody.
 
 
 
0
 

Author Comment

by:coder1313514512456
ID: 24391191
Arnold, you are truly a talented individual.  The idea to execute a which on the first column of the apropos result list works.

I had to tweak your script just a little (you were doing a which on the column result, so it would try commands like "ls(1)" instead of "ls"), and it works perfectly.  It also shows that there are commands defined in other sections from 2 through 7, in addition to sections 1 and 8.  And this makes it really easy to also see what kinds of commands are in each section, like:   2: chmod,kill,mkdir;  3: login, logout, time;  4: ip6, route, tty;  5: crontab, passwd, uuencode;  6: banner;  7: hostname, etc.

The only thing it doesn't do (yet, anyway) is parse the apropos listing if there are commands that are listed in a comma delimited group.  Know what I mean?  So like, if apropos returns a group and then defines them, and this grouping starts with a C API but the group contains a command, the group will be ignored.

I'm going to keep this question open a little longer in case anyone can sort out the grouping problem.  I guess what you would have to do is loop as long as the apropos column you're examining ends with a comma.  Ideally only the commands of the group would be listed, but this could get complex, at least from a scripting standpoint.

I'm including the code so far.


The following "command-only apropos" works in OS X 10.5.6-9G55 (Darwin) bash 3.2.17(1), however, it lists entire apropos groups if the first in the group is a command, and ignores groups entirely if the first in the group is a C API!
 

#!/bin/bash
 

if [ -z $1 ]

        then

        echo "Usage: $0 keyword";

        exit;

fi
 

apropos $1 | while read a

        do  

        set $a

        which `echo $1 | awk '{ print substr($1, 1, index($1, "(")-1)}'` >/dev/null 2>&1

        if [ "$?" -eq "0" ]

                then

                echo "$a"

        fi  

done

Open in new window

0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 76

Expert Comment

by:arnold
ID: 24392151
Post a sample output of apropos that you mentioned.
apropos on systems usually returns:
ls (1) etc.

It is not that difficult to incoporate a check for a comma in the first elemet. and then run it through a for loop or split the group on a comma. splitting can be done in a perl one liner.

0
 

Author Comment

by:coder1313514512456
ID: 24397442
Sure.  Here's an example of apropos output, you can see that in Darwin/Mac OS X the parenthesis is immediately next to the command.  Is a split that difficult to do in awk?  I'd prefer awk (or sed) to perl only because it seems that perl isn't necessarily distributed with all flavors of unix and unix-like OSes.  (Though I think they certainly should be!  :) )

Also: ozo, gheist, and omarfarid:  I finally get what you are saying now.  The man pages for Linux and Solaris are organized differently than OS X and they have it so that user (1) and admin (8) commands are grouped in those sections, that makes a lot of sense and is good to know for when I'm using those systems.  And I could have sworn I used a system once that had an apropos switch option to list commands (like apropos -k or something?  An old Unix on HP or an HP/UX?).

Thanks again guys.

Example of grouping and apropos output without space near paren in OS X:
 

$ apropos 'print lines matching a pattern'

grep(1), egrep(1), fgrep(1) - print lines matching a pattern

Open in new window

0
 
LVL 76

Expert Comment

by:arnold
ID: 24397900
It might be easier to setup a perl script to handle this type of issue or add additional logic to check the length of the response.  I have to think on what the better approach would be.
0
 

Author Comment

by:coder1313514512456
ID: 24398070
I would like to avoid perl if I can.  (I do appreciate perl!)

It would appear the awk has a split procedure that I totally forgot about.  I can't look at this right now, I'll have to revisit it in a little bit.
0
 
LVL 9

Assisted Solution

by:svs
svs earned 50 total points
ID: 24420956
"Although (1) and (8) do appear for commands, the problem is that they don't filter the other way, that is, they also contain C APIs"

That shouldn't be happening. Try this:

apropos man | egrep '\([18]\)'

( and ) have special meaning in egrep, they have to be escaped with \
0
 

Author Comment

by:coder1313514512456
ID: 24424385

sys:

In my version of OS X (now 10.5.7/9J61-Darwin 9.7.0), some examples of some (1) man pages that are not commands include stuff like bash built in commands (see builtin) like alloc, shift, source, stop, etc., and file stuff like finger.conf (which even though it is 5 will often show up on 1, again just an example),  And of course there's always commands that just aren't installed but will show in apropos (but the _which_ command does nicely filter them out via Arnold's script).

I'm still trying to get time together to work on the awk split idea.

Arnold:  Is this -very- easy in perl, or is it the case that it just can be done?  Do you prefix all perl scripts with "perl" or something?

0
 
LVL 76

Assisted Solution

by:arnold
arnold earned 370 total points
ID: 24424605
In some way the grouping you got is because what you were searching for matched multiple manual pages.  The grouping response returned manual pages that have the content you were looking for.  If the commands themselves are included in the response, I would skip the grouped line as of little or no consequence.
text spliting is simpler with perl, you could use bash, sed to replace the comma with a space and then run a for loop.
for i in $test
.

$list=echo $a | sed -e 's/\,/ /'g
for i in $list

The problem is that analyzing group, you will not have the explanation of the command as you would otherwise.

Perl is fairly simple
@array=split(/,/,$variable);
$#array  will return the number of elements in the array.



0
 

Author Comment

by:coder1313514512456
ID: 24431879
So Arnold what you are saying is I would have to make sure I nabbed the description with the group, then output each name with an appended description.
And the description, I suppose, would be defined as starting with two spaces and ending with $ endline?
 
 
 
0
 
LVL 76

Assisted Solution

by:arnold
arnold earned 370 total points
ID: 24434796
The grouped items are really not commands but references to manual pages that matched your search criteria.
apropos 'some text in describing function'
item1(1), item2(2), item3(1) - some text in describing function
item1 item1(1) - some text in describing function
item2 item2(2) - some text in describing function
item3 item3(1) - some text in describing function


You are not losing any data/commands by ignoring the grouped manual pages line.

Since the information is not lost by ignoring the grouped data, the added parsing/logic to evaluate the grouped data adds unnecessary checks.

Logically the grouped output is not a list of commands but a list of manual pages.

If you really want to incorporate the group into your command:
replace the which line with:
which `echo $a |awk -F\- ' { print $1 } ' | sed -e 's/,//g' -e 's/([0-9]*)//g'`
What the above will do is split on the - and take the first item.
sed will strip out the commas first and then strip the manual page section.
If you want to maintain the description, you should assign the awk -F\- ' {print $2 } to a variable.
0
 
LVL 9

Assisted Solution

by:svs
svs earned 50 total points
ID: 24436375
The perfect is the enemy of the good.  apropos | egrep one-liner is good enough, why bother?
0
 

Author Comment

by:coder1313514512456
ID: 24445204
sys - apropos | egrep is close but it doesn't entirely work on my system.  But I am very satisfied with the responses I've received.
I'm going to close this.  Thanks everyone, especially Arnold!
 
0
 

Author Closing Comment

by:coder1313514512456
ID: 31580814
Thanks everyone, you guys are great!
0
 

Author Comment

by:coder1313514512456
ID: 24455814
sys:  Let me just say one more thing here, that I totally agree with you that "perfect is the enemy of the good".  It is far too easy to gold plate code when you can just get what you need, much more efficient.
I didn't really see a way to comment to users directly (nothing in the profile areas), so that's why I'm writing this here.
 
 
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Using libpcap/Jpcap to capture and send packets on Solaris version (10/11) Library used: 1.      Libpcap (http://www.tcpdump.org) Version 1.2 2.      Jpcap(http://netresearch.ics.uci.edu/kfujii/Jpcap/doc/index.html) Version 0.6 Prerequisite: 1.      GCC …
Active Directory replication delay is the cause to many problems.  Here is a super easy script to force Active Directory replication to all sites with by using an elevated PowerShell command prompt, and a tool to verify your changes.
Learn several ways to interact with files and get file information from the bash shell. ls lists the contents of a directory: Using the -a flag displays hidden files: Using the -l flag formats the output in a long list: The file command gives us mor…
Learn how to find files with the shell using the find and locate commands. Use locate to find a needle in a haystack.: With locate, check if the file still exists.: Use find to get the actual location of the file.:

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now