5

I want to write my Bash functions each in a separate file, for easier version control, and source the whole lot of them in my .bashrc.

Is there a more robust way than e.g.:

. ~/.bash_functions/*.sh
Wildcard
  • 36,499
  • 5
    Define "robust". – Michael Homer Mar 19 '16 at 04:20
  • @MichaelHomer, how about—won't break if the directory is missing, won't break if the directory is empty, won't provide huge amounts of noise if there are a lot of files in that directory without read permissions.... – Wildcard Mar 19 '16 at 04:31
  • 1
    I do see your point, though, since if the functions/scripts are incorrectly/maliciously written it's not going to be "robust" in any meaningful way even if fulfills all of the above. The above would be enough for me. – Wildcard Mar 19 '16 at 04:31

2 Answers2

7

It's simply a matter of surrounding it all with appropriate error checks:

fn_dir=~/.bash_functions
if [ -d "$fn_dir" ]; then
    for file in "$fn_dir"/*; do
        [ -r "$file" ] && . "$file"
    done
fi
Warren Young
  • 72,032
  • What does the line that starts with [ -r "$file ] mean? Some explanation would be helpful. – user9101329 Jun 29 '23 at 07:16
  • It could be rewritten "if [ -r "$file" ] ; then source "$file" ; fi". On Unix systems, [ is an alias (often a hardlink) to /bin/test, a program that evaluates its arguments and returns 0 or nonzero in response, which you can then react to in a script using either if or embedded && type logic. It's a style choice, not a functional one. The one who edited my script thus feels it's better to be terse than verbose. You can argue over which is clearer, but both are correct. – Warren Young Jun 29 '23 at 16:43
1

As for source multiple files at once, it can be done by creating a redirect of it's concatenated output, like:

source <(cat ~/.bash_functions/*.sh)

As for the robust part you might need to have an error check properly set for whatever you're sourcing, such as:

source <(cat ~/.bash_functions/*.sh)||echo "ERROR: failed while sourcing $?";exit 1

here is another snippet, where you can also validate the sourced files it-self like:

sourced_files=$(source <(cat ~/.bash_functions/*.sh) 2>&1 > /dev/null)
if [ -n "$sourced_files" ]; then
 echo "ERROR: nonzero returned"
fi

Would be even better if possible to add an error validation inside whatever you're sourcing, with custom error codes so you can have a better track where it failed, such as:

err=0
...
...
# your shell script
...
some-command-i-wanna-check
if [ "$?" -ne 0 ];then
 echo "ERROR: my failed description"
 err=101
 exit $err 
fi
isca
  • 127