I have a bash script initial-tests.bash
that runs some tests, using another script with pure functions. It looks something like:
#! /bin/bash
source ./scripts/_functions.bash
check=$(do_check)
echo "$check"
The script _functions.bash
contains this:
#! /bin/bash
# Here we save reusable functions to aid the other scripts
echoerr() {
# Output to stderr while freeing stdout for returns
echo -ne $red
echo "ERROR: $*" | ts '[%Y-%m-%d %H:%M:%S]' 1>&2
echo -ne $nc
}
first_check() {
echoerr "This is an echoerr with echo -e"
echo false
}
do_check() {
local x
x=$(first_check)
if [[ "$x" = 'false' ]]; then
echo
else
echo false
fi
}
initial-tests.bash
is in turn sourced by another script main.bash
:
#! /bin/bash
nc='\e[0m'
yellow='\e[1;33m'
green='\e[1;32m'
red='\e[1;31m'
blue='\e[1;34m'
# Fail early in case of argumentation error
echo -e "${blue}- - - Initial Checks - - -${nc}"
source ./scripts/initial-checks-load-config.bash
The tests' outputs are correct when I source
that script directly: source scripts/initial-tests.bash
:
[2024-10-10 08:30:55] ERROR: This is an echoerr with echo -e
But when I run bash main.bash
, the tests are wrong:
- - - Initial Checks - - -
[2024-10-10 08:30:49] ERROR: This is an echoerr with echo -e
false
Note that false
should be empty.
It is not clear to me why source
is producing a different result from the bash
run.
More info:
It seems that my problem is a mixture of:
initial-tests.bash
in case it is run directly and not via main.bash
(the colour escape sequences)echo -ne $nc
as the last command in echoerr
, which is not outputting a newline character and thus, in effect, is prepending $nc
to the echo
that immediately follows in first_check
function.Regarding point 1, when I run bash main.bash
and then source initial-tests.bash
, the sourced script will have access to the colour escape sequences. But when I directly source initial-tests.bash
, and since the colour sequences are not (re-)defined within, these colour sequences are blank.
Regarding point 2, using -n
prepends to next echo:
echo -n hi; echo bye
> hibye
When $nc
is blank due to sourcing initial-tests.bash
directly as explained, function first_check
is producing a mere false since nothing is prepended to 'false' because $nc
is empty:
echo -ne $nc (last command in echoerr)
echo false
And the if
test in do_check
passes:
if [[ "$x" = 'false' ]]; then
echo
else
echo false
fi
=> so output is ''.
However, when I run bash main.bash
, $nc
contains a colour escape sequence, so that sequence is prepended to false and is making the same test fail, and hence going to the else, and echoing 'false' instead of nothing => so output is 'false'. It was tricky to detect since the prepended value was an escape sequence.
I could fix this by:
echo -n
from echoerr
to avoid prepending anything to the immediate next echo.