Importing functions from a shell script

shell

Solution

According to the “Shell Builtin Commands” section of the bash manpage, `.` aka `source` takes an optional list of arguments which are passed to the script being sourced. You could use that to introduce a do-nothing option. For example, `script.sh` could be:

#!/bin/sh

foo() {
    echo foo $1
}

main() {
    foo 1
    foo 2
}

if [ "${1}" != "--source-only" ]; then
    main "${@}"
fi

and `unit.sh` could be:

#!/bin/bash

. ./script.sh --source-only

foo 3

Then `script.sh` will behave normally, and `unit.sh` will have access to all the functions from `script.sh` but will not invoke the `main()` code.

Note that the extra arguments to `source` are not in POSIX, so `/bin/sh` might not handle it—hence the `#!/bin/bash` at the start of `unit.sh`.

Problem

I have a shell script that I would like to test with shUnit. The script (and all the functions) are in a single file since it makes installation much easier. Example for `script.sh` ``` #!/bin/sh foo () { ... } bar () { ... } code ``` I wanted to write a second file (that does not need to be distributed and installed) to test the functions defined in `script.sh` Something like `run_tests.sh` ``` #!/bin/sh . script.sh # Unit tests ``` Now the problem lies in the `.` (or `source` in Bash). It does not only parse function definitions but also executes the code in the script. Since the script with no arguments does nothing bad I could ``` . script.sh > /dev/null 2>&1 ``` but I was wondering if there is a better way to achieve my goal. Edit My proposed workaround does not work in the case the sourced script calls `exit` so I have to trap the exit ``` #!/bin/sh trap run_tests ERR EXIT run_tests() { ... } . script.sh ``` The `run_tests` function is called but as soon as I redirect the output of the source command the functions in the script are not parsed and are not available in the trap handler This works but I get the output of `script.sh`: ``` #!/bin/sh trap run_tests ERR EXIT run_tests() { function_defined_in_script_sh } . script.sh ``` This does not print the output but I get an error that the function is not defined: ``` #!/bin/sh trap run_tests ERR EXIT run_tests() { function_defined_in_script_sh } . script.sh | grep OUTPUT_THAT_DOES_NOT_EXISTS ``` This does not print the output and the `run_tests` trap handler is not called at all: ``` #!/bin/sh trap run_tests ERR EXIT run_tests() { function_defined_in_script_sh } . script.sh > /dev/null ```

Original source

Related problems