Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Do you have any easy idea to define some alias in .bashrc for finding some command that you want to search (when you forgot its name) in your machine, visiting all "bin" directories, maybe using regex?

e.g.

ls /bin /sbin /usr/bin | grep program

Do you have any idea how to use regex for searching all bin directories?

share|improve this question

migrated from stackoverflow.com Mar 12 '12 at 20:08

This question came from our site for professional and enthusiast programmers.

    
Did I misunderstand, and you aren't searching for regex or names, you don't remember exactly? –  user unknown Mar 13 '12 at 5:00

8 Answers 8

up vote 3 down vote accepted

you can use whereis to find all binaries matching the name you are searching for

> whereis -b ls
ls: /bin/ls

-b option is for binaries only, without it you will find sources and man page files as well

> whereis ls
ls: /bin/ls /usr/share/man/man1/ls.1.gz
share|improve this answer

This one works with no external dependencies (only shell builtins) and will work with busybox ash as well.

Sometimes you cant remember how to spell it exactly though, for those of us who just need to find a close match, there is this function to add to the bashrc:

find_bin(){
for x in ${PATH//://*${1}* }*${1}*; do
    [ -f "$x" ] && echo $x
done
}

find_bin grep will list all of the binaries in $PATH with grep in the name along with their path {grep, egrep, fgrep, bugreport,... }

this can accept the following syntax:

  • a*z - with az
  • a?z - with a<1 character>z
  • a[0-9]z - with az
  • a[a-z]z - with az
  • a[A-Z]z - with az
  • a*{a,z}*z - with a .... same as a[az]z

if you occasionally want it to only match the whole word and not report egrep, fgrep or bugreport when you type grep, you can remove the asterisks and add them back at the command line only where you want them

find_bin(){
for x in ${PATH//://${1} }${1}; do
    [ -f "$x" ] && echo $x
done
}

for this one extra syntax is needed for matching the beginnings and endings

  • *grep - will match commands ending in gre (will find grep,egrep and fgrep, but not bugreport)
  • grep - will only match exact string grep
  • grep* - will match commands beginning with grep
  • all patterns above apply as well
share|improve this answer
    
find_bin "[aeiou]b.*" does not find ''ubuntu-bug'' or ''ebrowse''. Your script uses globbing, not regexes, afaik, but I don't really understand ` ${PATH//://*${1}* }*${1}*` –  user unknown Mar 14 '12 at 10:20
    
The op said "maybe using regex". for file names globbing is good enough 99% of the time. Other solutions require tools that may not be available to the shell - for instance, my box doesn't have whereis, while this uses built-ins that will work on nearly all shells - though I should add type $1 to see if it is an alias or function in a bashrc. ${PATH//://*${1}* }*${1}* is substring manipulation, it replaces the ':'s in PATH with a "*[the first arg]*space" the last one is needed because there is no colon on the end, thus grokking it into something for ... in ... can use. –  technosaurus Mar 14 '12 at 13:00
    
+1 for the explanation. Now I understand the expression. –  user unknown Mar 14 '12 at 15:13

Use the bash function type. It's better than whereis because it will identify functions built into bash and aliases as well as binary executables. whereis is better because it will do some pattern matching -- type only find the thing you specify.

Use the -a option to show all occurrences of the executable in your path.

~$ type python
python is /usr/local/bin/python
~$ type -a python
python is /usr/local/bin/python
python is /usr/bin/python
python is /usr/local/bin/python
~$ whereis -b python
python: /usr/bin/python /usr/bin/python2.4 /usr/lib/python2.4 /usr/local/bin/python /usr/local/bin/python2.6 /usr/local/bin/python2.5 /usr/local/bin/python2.7 /usr/local/bin/python2.7-config /usr/local/bin/python2.5-config /usr/local/bin/python2.6-config /usr/local/lib/python2.6 /usr/local/lib/python2.5 /usr/local/lib/python2.7 /usr/include/python2.4

~$ whereis -b time
time: /usr/bin/time /usr/include/time.h
~$ type -a time
time is a shell keyword
time is /usr/bin/time
share|improve this answer
    
This was the best answer for me. I need to store a program's path to a variable and I did that with following: PATH='type -p ffmpeg' (replace single quotes with backtics). Thank you, Doug harris. I hope my example helps others, too :) –  user1383815 May 3 at 6:17

which does exactly that:

which commandname
share|improve this answer
    
Apart from the regex part, to search for not completly known names. –  user unknown Mar 13 '12 at 4:59

To put it into your .bashrc, an alias isn't useful because aliases don't take parameters, but a function will do:

pfind () {
  for d in ${PATH//:/ }
  do
    find $d -regex $d/"$1"
  done
}

pfind '.*[ou]b.*h'

find ... -reges searches for regular expressions for the whole path, so we need to repeat $d.

pfind shall stand for program-find (or PATH find).

share|improve this answer
    
In case you have a directory with spaces, a safer way to iterate is: IFS=:; for dir in $PATH; do ...; done. Also, instead of parsing ls, just use globbing directory: echo *"$1"* (not regular expressions though. –  glenn jackman Mar 12 '12 at 23:43
    
echo $d/* in above command would output all entries of the directory, if one file matches - independent from regexes or not. Normally, I advocate against using ls, so I tried it here too - and find is a fine solution (you normally don't have directories below ~/bin, else add an -maxdepth 1 to the find params after the path. –  user unknown Mar 13 '12 at 4:57

You can use man -k to search inside the manpage of each command:

man -k packet


PF_PACKET (7)        - packet interface on device level.
gpgsplit (1)         - Split an OpenPGP message into packets
ip6tables (8)        - IPv6 packet filter administration
iptables (8)         - administration tool for IPv4 packet filtering and NAT
lft (1)              - print the route packets trace to network host
lft.db (1)           - print the route packets trace to network host
packet (7)           - packet interface on device level.
pcap-filter (7)      - packet filter syntax
tc-bfifo (8)         - Packet limited First In, First Out queue
tc-pfifo (8)         - Packet limited First In, First Out queue
tcptraceroute (1)    - A traceroute implementation using TCP packets
tcptraceroute.db (8) - print the route packets trace to network host
tcptraceroute.mt (1) - A traceroute implementation using TCP packets
traceproto (1)       - print the route packets trace to network host
traceproto.db (1)    - print the route packets trace to network host
traceroute (1)       - print the route packets trace to network host
traceroute-nanog (1) - print the route packets trace to network host
traceroute.db (1)    - print the route packets trace to network host
traceroute6 (1)      - print the route packets trace to network host
traceroute6.db (1)   - print the route packets trace to network host


man -k "packet limited"
tc-bfifo (8)         - Packet limited First In, First Out queue
tc-pfifo (8)         - Packet limited First In, First Out queue

The numbers inside parenthesis represents the section of the man page of the command, section 3 and 5 for example are not for commands, of course you have to consider that sadly some commands do not have a man page.

share|improve this answer

In bash, if you remember the first character or two of a command, type <character><character><TAB><TAB> to see the list of all commands whose name starts with <character><character>.

In Linux, "locate string" will list all files and directories with "string" as part of its name. (You'd need to have built its DB first, with updatedb. On CentOS, a cron.daily job runs updatedb.) This won't tell you which one might be executable; it's just another way to find more info.

share|improve this answer

Assuming you have a mlocate package:

locate programname
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.