bash(1)
isn’t all that “magic,” though it certainly makes its users feel like wizards! The key to deciphering it is to know which manpages to look at. Or, if you are a language person (like me), to realize that bash is one little glue language; a bunch of other little languages are sprinkled on top of it in the form of little tools like grep(1)
, sed(1)
, awk(1)
, cut(1)
, etc.
So, let’s dig in:
[ $# = 0 ] && help
This says, run the [
test command; if it succeeds, run the help command. $#
is the number of arguments. Run help test
at your shell to get a good idea of its workings (help
only works for builtins—for the rest you need man(1)
).
while [ $# -gt 0 ]; do
The beginning of a while loop. To note: most modern bash programmers would use either [[ $# > 0 ]]
(unless they need ti be POSIX-sh compatible) or (($# > 0))
.
CMD=$(...)
Run the stuff in parens and store the output in CMD (the manual for bash clarifies how this works).
grep ... go.sh
Searches go.sh
for a particular pattern (see man re_format
for the gory details of regular expressions, and man grep
for what the options do—for example, -o
means print only the match instead of the whole line).
| sed ...
Output the results of grep as the input to sed. man sed
is a good resource for its little language. s/-/_/g
substitutes all -
for _
; a more idiomatic way to do that would be to use tr instead of sed: tr - _
.
if [ -z ... ]
Test if the argument is empty. The rest of the if logs a message and exits.
shift
Pops a command line argument off of $@
, so now there’s one less.
eval "$CMD" "$@"
Run the CMD string (better would be to use an array here) with the remaining arguments.
|| shift $? 2>/dev/null
If it fails, shift off as many arguments as the exit code ($?
), and redirect error messages to /dev/null
(such as when there aren’t enough arguments to shift).
This part is a little bizarre, and probably only makes sense in the context of the application. Generally, exit codes don’t tell you what to shift. But you could program something that way.