viernes, 8 de junio de 2012

*findhere* Searching through "whereis" output directories

This morning I was trying to find python's mechanize plugin source code to look into its docstrings.
Having a little hard time finding where that little file should be located I wrote this little bash script.

It takes 2 arguments, first the string to feed whereis (locates binaries, source code, and manuals) then, the string you're looking for that might be inside the folders of that binary.

#!/bin/bash

##############################################################################
#Thanks to http://ubuntuforums.org/showthread.php?t=642704
#
# ----------------------------------------------------------------------------
# "THE SODA-WARE LICENSE" (Revision 42):
# <http://reikaze.blogspot.mx/> author wrote this file. As long as you retain 
# this notice you can do whatever you want with this stuff. If we meet some 
# day, and you think this stuff is worth it, you can buy me a coke in return.
# ----------------------------------------------------------------------------
#
# Takes 2 arguments:
#    1st: Will use it with "whereis" command, to find binaries locations
#    2nd: The string that should be search for inside the binary locations
#
##############################################################################

output=$(whereis $1)
array=($output)
for i in $(seq 1 $((${#array[*]} - 1))); do
 result=$(find ${array[$i]} -iname $2 2>/dev/null)
 if [ "$result" != "" ];
 then echo $result
 fi
done
For those who want to learn a little about bash scripting:

"#!/bin/bash"
Will indicate the script interpreter that should be used to run this script.

"$(whereis $1)"
Executes whereis with the first argument. The output will be saved on output variable.

"array=($output)"
Will make an array from whereis output, it's divided with whitespaces.

"for i in $(seq 1 $((${#array[*]} - 1))); do"
The beginning of a loop through every element of the array.
If the array has 6 elements, will go through the second (1) to the last element (5) --the array begins on the (0) element.
"seq" command will output a sequence of numbers, in this case, from 1 to 5. And each number will be saved in "i" on each iteration. ${array[*]}: refers to every element of "array"
${#array[*]}: is the total elements of "array".
So, (${#array[*]} - 1) = (6-1) = 5.
Then, $(seq 1 $((${#array[*]} - 1))) = $(seq 1 5) = 1 2 3 4 5
Finally, in the example given the sentence will mean "for i in 1 2 3 4 5; do"

"result=$(find ${array[$i]} -iname $2 2>/dev/null)"
Will look for this script's second argument ($2) on each location stored on "array"
e.g. find /usr/lib/python2.7 -iname mechanize
2>/dev/null means that every error will be ignored (some of the results of whereis are files not folders)
/dev/null is a device that does nothing, it's like a black hole.
2 is the output error buffer
">" is used to redirect output buffers
Well I hope this would be useful for somebody else.