1

This is probably something very silly, but I cannot find any answers anywhere. I've tried to setup a .bashrc.d directory with scripts to source within .bashrc, to make the process more organised. Instead of manually sourcing each script in .bashrc.d, I'm sourcing them in this way:

if [ -d "$HOME/.bashrc.d" ]; then
    find "$HOME/.bashrc.d/" -type f -name "*.sh" | sort | \
        while read -r f; do
            source "$f"
        done
fi

However, source "$f" seems to be running inside a subshell, because the command doesn't actually source any of the files. It executes them as I can see by the output of set -x, but e.g. none of the variable exports carry to the original iteractive shell. I also know this is a problem with sourcing inside the while loop and not with sourcing from .bashrc, since manually sourcing these files actually works (albeit it doesn't solve this issue). What is even happening and how do I fix this?

2 Answers2

3

You're right that you run source in a subshell. To fix it you can simply loop through the files without piping output of find:

for script in "$HOME"/.bashrc.d/*.sh
do
    if [ -r "$script" ]
    then
        . "$script"
    fi
done
  • Might be worth mentioning that the glob is also sorted by default, giving similar results as find | sort. Though the glob wouldn't look into subdirectories of .bashrc.d/, but then I'm not sure if that's usually done for .d directories anyway. – ilkkachu Jan 02 '22 at 22:36
2

It's the pipes and not the while that make the command run in subshell. Setting the lastpipe option doesn't help in an interactive shell with job control. Try a "process substitution" ( should your bash version provide that):

while read -r f; do source "$f"; done < <( find "$HOME/.bashrc.d/" -type f -name "*.sh" | sort ) 
RudiC
  • 8,969