Background
I hate when people make little shell scripts that all do essentially the same thing. For example:
1 2 3 4 |
process_moe_dir.bash process_larry_dir.bash process_curly_dir.bash process_schemp_dir.bash |
Here’s a technique to roll these all into a single shell script that you can just call with a command line argument.
Solution
Instead of creating the 4 scripts above, we’re going to create just one script like this one below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#!/bin/bash # vim: ts=2 moe_dir="/path/to/moe" larry_dir="/path/to/larry" curly_dir="/another/path/to/somewhere/curly" schemp_dir="/another/path/to/somewhere/else/schemp" case "$1" in moe|larry|curly|schemp ) cmd_arg="$1" active_dir=$(eval "echo \${$(echo ${cmd_arg}_dir)}") echo "active_dir: $active_dir" echo "" ;; * ) echo "" echo "USAGE: `basename $0` [moe|larry|curly|schemp]" echo "" exit 1 ;; esac |
Here’s the script in action:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
% ./dyn_variable_ex.bash USAGE: dyn_variable_ex.bash [moe|larry|curly|schemp] % ./dyn_variable_ex.bash moe active_dir: /path/to/moe % ./dyn_variable_ex.bash larry active_dir: /path/to/larry % ./dyn_variable_ex.bash curly active_dir: /another/path/to/somewhere/curly % ./dyn_variable_ex.bash schemp active_dir: /another/path/to/somewhere/else/schemp |
The key concept in the above script is the notion of dynamic variable names. This is the line that makes the dynamic variables work.
1 |
active_dir=$(eval "echo \${$(echo ${cmd_arg}_dir)}") |
Within this line are 2 commands, in the form of $(…).
NOTE: one of these is nested inside of the other i.e. $( $() ).
… so for example: say ${cmd_arg} = moe
- The inner: $(..) –> $(echo ${cmd_arg}_dir) echoes the string moe_dir.
- The outer: $(..) –> $(eval “echo \${moe_dir}”) echoes the contents of $moe_dir
Useful Links
NOTE: For further details regarding my one-liner blog posts, check out my one-liner style guide primer.