Bash: function "command not found" in a subshell

A function defined in your shell is invisible to subshells and child processes unless exported with `export -f` or sourced in the child.

Error String

bash: my_function: command not found

Tldr

Bash functions are local to the shell that defined them. `bash -c` subprocesses, scripts, and other tools that exec a new shell don't inherit them. Export with `export -f my_function`, or source the defining file from the child.

Cause

Common when piping to `sudo bash -c …` or `parallel` — the function exists in the calling shell but the child shell starts empty.

Repro

greet() { echo "hi $1"; }
greet alice                   # works
bash -c 'greet bob'           # command not found

Fix

greet() { echo "hi $1"; }
export -f greet
bash -c 'greet bob'           # hi bob

# Or source the file in the child:
bash -c 'source /path/to/lib.sh; greet bob'

Explanation

`export -f` works for Bash subshells but not POSIX `sh`. For maximum portability, put helpers in a sourceable file and source it explicitly from every entry point.

Faq

Q

Why is my function missing inside find -exec?

A

`find` executes a new process, and functions are not inherited. Export it and invoke through `bash -c`, or use a wrapper script.

Q

Does sourcing inside a function make it global?

A

Yes, sourced definitions land in the current shell — but only from the point of sourcing onwards.

Deep Dive

Heading

Definition order matters

Body

A shell script is executed as it is read, so a function must be defined before the line that calls it. Definitions inside an `if` branch that did not run, or in a file that was never sourced, leave the name undefined. Check with `declare -f name` at the call site: it prints the body if the function exists and returns non-zero if it does not. `type name` shows whether the name resolves to a function, builtin, alias or file.

Heading

Subshells and exported functions

Body

Functions do not cross process boundaries. A function is invisible to `xargs`, `find -exec`, `sudo`, `su`, `ssh`, or any separate `bash` invocation unless you export it with `export -f name` and the child is Bash. `xargs bash -c 'my_func "$@"' _` works only after the export. In `sudo` the environment is scrubbed by default, so the cleanest approach is to move shared helpers into a library file and `source` it in every context that needs them.

Checklist

Move the definition above the first call.

Confirm the sourced library path is correct and readable.

Run `declare -f name` at the call site to check visibility.

Use `export -f` for functions consumed by child Bash processes.