find ${settings_base} -type f -exec source {} \;
find: ‘source’: No such file or directory
for f in $(find ${settings_base} -type f); do
source "${f}"
done
I just want to know the reason for FAIL.
The -exec predicate of find runs a subprocess. But source cannot be run as a subprocess.
Shell built-ins like source (and cd, etc) modify the environment of the currently running shell instance. They don't exist as external commands (there is no /bin/source or /usr/bin/source etc) because they cannot work as external commands. Recall that a subprocess cannot modify the environment of its parent process, for reasons of security as well as for architectural reasons (see also e.g. Global environment variables in a shell script for background). So as a matter of fact, even if find could somehow execute source, it could only modify the environment of the find process, and then when find exits, any effects of that would be lost, and your currently running shell instance would be back where it was before you ran find.
The workaround you already discovered is the way to do it, though for complete robustness, you would also have to guard against whitespace or other shell metacharacters in the find output. https://mywiki.wooledge.org/BashFAQ/020 has a detailed discussion, but I won't repeat all the nuances and corner cases here; click through to the linked page for that.
while IFS= read -r -d '' f; do
source "$f"
done < <(find $settings_base -type f -print0)
(Notice that -print0 is a GNU extension, and so not properly portable to various non-Linux platforms.)
Depending on what $settings_base contains, it should probably be double-quoted; if it contains multiple values, put them in an array and use "${settings_base_array[@]}". See also When to wrap quotes around a shell variable?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With