man(1) continued

How do I find commands?

Once upon a time, we talked a bit about man pages, and how useful they are for learning about a new program. We didn’t really get into how you find programs that you might want to run. This is what we’ll start exploring in the rest of this post.

First, a few things to know. Most executable files, also called “binaries” are stored in a bin directory. This is just convention, since technically a binary file can live anywhere. There are generally a few bin directories on any given UNIX system. Some of them are:

/bin - User utilities fundamental to both single and multi-user environments. These programs are statically compiled and therefore do not depend on any system libraries to run.

/sbin - System programs and administration utilities fundamental to both single and multi-user environments. These programs are statically compiled and therefore do not depend on any system libraries to run.

/usr/bin - Common utilities, programming tools, and applications.

/usr/sbin - System daemons and utilities (executed by users).

/usr/local/bin - Local executables, libraries, etc.

/usr/local/sbin - Local executables, libraries, etc.1

But, there can be many more. A quick use of the find(1) command (we talked about find last week) can help me get a picture of how many there are on my system:

$ find / -type d -name "bin"
find: /home/erica/.ssh: Permission denied
/usr/X11R6/bin
/usr/local/bin
/usr/bin
find: /usr/libexec/auth: Permission denied
find: /var/authpf: Permission denied
find: /var/backups: Permission denied
find: /var/cron/atjobs: Permission denied
find: /var/cron/tabs: Permission denied
find: /var/db/ldap: Permission denied
find: /var/db/yubikey: Permission denied
find: /var/games/hackdir/save: Permission denied
find: /var/nsd/etc: Permission denied
find: /var/nsd/run/xfr: Permission denied
find: /var/quotas: Permission denied
/var/spool/ftp/bin
find: /var/spool/ftp/bin: Permission denied
find: /var/spool/ftp/etc: Permission denied
find: /var/spool/ftp/hidden: Permission denied
find: /var/spool/smtpd: Permission denied
/var/www/bin
find: /var/www/cache: Permission denied
find: /var/sysmerge: Permission denied
/bin
find: /etc/iked/private: Permission denied
find: /etc/isakmpd/private: Permission denied
find: /etc/ldap/certs: Permission denied
find: /etc/skel/.ssh: Permission denied
find: /etc/ssl/private: Permission denied
find: /etc/ssl/acme/private: Permission denied
find: /etc/acme: Permission denied
find: /root: Permission denied

That’s a lot more output than I care about, so I can use two more tools we’ve learned about previously to clean it up a bit. I’m going to use the pipe operator | to send the output of my find command to the grep command. I’m also going to tell grep to ignore (-v) lines that match the pattern “Permission Denied”:

$ find / -type d -name "bin" |grep -v "Permission denied"
find: /home/erica/.ssh: Permission denied
/usr/X11R6/bin
/usr/local/bin
/usr/bin
find: /usr/libexec/auth: Permission denied
find: /var/authpf: Permission denied
find: /var/backups: Permission denied
find: /var/cron/atjobs: Permission denied
find: /var/cron/tabs: Permission denied
find: /var/db/ldap: Permission denied
find: /var/db/yubikey: Permission denied
find: /var/games/hackdir/save: Permission denied
find: /var/nsd/etc: Permission denied
find: /var/nsd/run/xfr: Permission denied
find: /var/quotas: Permission denied
/var/spool/ftp/bin
find: /var/spool/ftp/bin: Permission denied
find: /var/spool/ftp/etc: Permission denied
find: /var/spool/ftp/hidden: Permission denied
find: /var/spool/smtpd: Permission denied
/var/www/bin
find: /var/www/cache: Permission denied
find: /var/sysmerge: Permission denied
/bin
find: /etc/iked/private: Permission denied
find: /etc/isakmpd/private: Permission denied
find: /etc/ldap/certs: Permission denied
find: /etc/skel/.ssh: Permission denied
find: /etc/ssl/private: Permission denied
find: /etc/ssl/acme/private: Permission denied
find: /etc/acme: Permission denied
find: /root: Permission denied

And, that did not work at all! The reason is the “Permission denied” message is being output on what is knows as “standard error” while the rest of the messages are being output on what is known as “standard output”. We’ll get into those in a later post, for now we’ll just fix the issue by redirecting standard error to standard output before piping it to grep:

$ find / -type d -name "bin" 2>1 |grep -v "Permission Denied"
/usr/X11R6/bin
/usr/local/bin
/usr/bin
/var/spool/ftp/bin
/var/www/bin
/bin

Nice. Finally we have the output we were looking for.

This is one of the things that I love about the command line. It can be such a rich learning environment. You go in thinking you’re just going to write a quick post on how to find commands, and next thing you know you have 3 more things you need to explain before you can do that.

All that to say, that there could be many bin dirs on your system, and there are generally “binaries” or “programs” in those directories. It can be fun to poke around in there and see what is available. You might find some gems. For example, say I’m feeling very “elly” and want to see some commands that start with the letter l:

$ cd /usr/bin
$ ls l*
lam       ld        less      libnetcfg locale    logger    look      lpr
last      ldd       lesskey   libtool   locate    login     lorder    lprm
lastcomm  leave     lex       lndir     lock      logname   lpq       ltrace

Voila! A bunch of programs that all start with the letter l, and all should have a man page I can read to learn more about. Sometimes when I’m bored, I just pick a random program from my system and read it’s man page.

Another good way to find programs that’s a bit less labour intensive is the apropos command, also known as man -k. You just pass a keyword to the apropos command and it will return you a list of programs that are related to that keyword. So, for example say I want to know about users, I could do:

$ man -k users
rusers(1) - who is logged in to machines on local network
users(1) - list current users
getusershell, endusershell, setusershell(3) - get legal user shells
npppd-users(5) - user database file
rpc.rusersd(8) - logged in users server
endusershell, setusershell, getusershell(3) - get legal user shells
crontab(1) - maintain crontab files for individual users
help(1) - help for new users and administrators
last(1) - indicate last logins of users, ttys, and hosts
mesg(1) - display (do not display) messages from other users
rwall(1) - send a message to users logged on a host
skeyaudit(1) - warn users if their S/Key will soon expire
w(1) - display users who are logged on and what they are doing
wall(1) - write a message to users
__thrsleep, __thrwakeup(2) - userspace thread sleep and wakeup
__thrwakeup, __thrsleep(2, 3) - userspace thread sleep and wakeup
Net::Netrc(3p) - OO interface to users netrc file
adduser, rmuser(8) - add and delete users from the system
rmuser, adduser(8) - add and delete users from the system
rpc.rwalld, rwalld(8) - write messages to users currently logged in server
rwalld, rpc.rwalld(8) - write messages to users currently logged in server

From there, you can read those man pages and find even more information, especially in the “See Also” section of the program’s man page. It’s not quite as fun as randomly clicking on Wikipedia links, but… a close second.

New Terms

stderr
Standard error. A magic place where errors can be sent. They will also echo on your screen.
stdout
Standard output. A magic place where output is sent. It also echo’s to your screen.
apropos
Equivalent to man -k but much more fun to type. A program for searching for man pages on a given topic.

Have a suggestion for a future post? A question about an article? Just want to say hi? Drop me an email: gabe@cotcli.com

Want to receive these posts directly to your inbox? Subscribe here.