This question is, if it matters, preferably in the context of Bash, but I would appreciate a cross-language solution.
The problem I'm encountering is in the context of "sourcing" a script with another, but doing this recursively. The problem is that it seems to do it infinitely.
The specific case is as follows. I've created a simple bash script to load other bash scripts in the same directory. Since in my project all scripts are in the same directory, this is OK for now.
So the "script loader" is as follows (a file _source_script.sh
which defines the following function):
_source_script()
{
# Define a few colors for the possible error messages below.
RED=$(tput setaf 1)
NORMAL=$(tput sgr0)
EXPECTED_DIR="scripts"
if [ "$#" -ge "1" ]
then
EXPECTED_DIR=$1
fi
# Based on: http://stackoverflow.com/a/1371283/3924118
CURRENT_DIR=${PWD##*/}
if [ "$CURRENT_DIR" = "$EXPECTED_DIR" ]
then
for (( arg = 2; arg <= $#; arg++ ))
do
# Based on:
# - http://askubuntu.com/questions/306851/how-to-import-a-variable-from-a-script
# - http://unix.stackexchange.com/questions/114300/whats-the-meaning-of-a-dot-before-a-command-in-shell
# - http://stackoverflow.com/questions/20094271/bash-using-dot-or-source-calling-another-script-what-is-difference
printf ". ./${!arg}.sh\n"
# Try to load script ${!arg}.sh
. ./${!arg}.sh
# If it was not loaded successfully, exit with status 1.
if [ $? -ne 0 ]
then
printf "${RED}Script '${!arg}.sh' not loaded successfully. Exiting...${NORMAL}\n"
exit 1
fi
done
else
printf "No script loaded: $CURRENT_DIR != $EXPECTED_DIR.\n"
exit 1
fi
}
To use this "script loader", other scripts must first "source" it as follows:
. ./_source_script.sh
The problem is when I try to include other scripts by sourcing them through the function _source_script
.
For example, when I tried to do (in script some_script.sh
):
_source_script scripts colors asserts clean_environment
it kept on running forever.
Inside colors.sh
I have:
#!/usr/bin/env bash
# Colors used when printing.
export GREEN=$(tput setaf 2)
export RED=$(tput setaf 1)
export NORMAL=$(tput sgr0)
export YELLOW=$(tput setaf 3)
Inside asserts.sh
I have:
...
. ./_source_script.sh
_source_script scripts colors
and inside clean_environment.sh
I also have:
. ./_source_script.sh
_source_script scripts colors
From my understanding, this should run recursively until it finds either a script which does not load anything or it finds a cycle, which isn't the case.
So, my solution was to have in some_script.sh
the following:
_source_script scripts colors
_source_script scripts asserts
_source_script scripts clean_environment
that is, run them individually.
So, why can't I "source" multiple scripts in a loop?