Skip to content

Instantly share code, notes, and snippets.

@gvlx
Forked from tvlooy/unit.sh
Last active October 5, 2018 05:47
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gvlx/0adfb1137937ad443df2eeaa73dc0ba7 to your computer and use it in GitHub Desktop.
Save gvlx/0adfb1137937ad443df2eeaa73dc0ba7 to your computer and use it in GitHub Desktop.
Bash test: get the directory of a script
#!/bin/bash
# Following stackoverflow discussion, from https://gist.github.com/tvlooy/cbfbdb111a4ebad8b93e (rev7)
function test(){
local __MESSAGE__="$1"
local __RECEIVED__="$2"
local __EXPECTED__="$3"
if [ "${__RECEIVED__}" == "${__EXPECTED__}" ]; then
# shellcheck disable=SC1117
echo -e "\033[32m✔ Tested ${__MESSAGE__}"
else
# shellcheck disable=SC1117
echo -e "\033[31m✘ Tested ${__MESSAGE__}"
echo -e " Received: ${__RECEIVED__}"
echo -e " Expected: ${__EXPECTED__}"
fi
# shellcheck disable=SC1117
echo -en "\033[0m"
}
function testSuite(){
test 'absolute call' "$(bash ${__TEMPDIR__}/1234/test.sh)" "${__TEMPDIR__}/1234"
test 'via symlinked dir' "$(bash ${__TEMPDIR__}/current/test.sh)" "${__TEMPDIR__}/1234"
test 'via symlinked file' "$(bash ${__TEMPDIR__}/test.sh)" "${__TEMPDIR__}/1234"
test 'via multiple symlinked dirs' "$(bash ${__TEMPDIR__}/current/loop/test.sh)" "${__TEMPDIR__}/1234"
pushd "${__TEMPDIR__}" >/dev/null || exit 1
test 'relative call' "$(bash 1234/test.sh)" "${__TEMPDIR__}/1234"
popd >/dev/null || exit 1
test 'with space in dir' "$(bash ${__TEMPDIR__}/12\ 34/test.sh)" "${__TEMPDIR__}/1234"
test 'with space in file' "$(bash ${__TEMPDIR__}/1234/te\ st.sh)" "${__TEMPDIR__}/1234"
echo
}
function readlink_exists(){
if [[ ! $(which readlink 2> /dev/null) ]]
then
# shellcheck disable=SC1117
echo -e "\033[31m✘ readlink not available, test skipped"
# shellcheck disable=SC1117
echo -e "\033[0m"
(exit 1)
fi;
}
function rm_tempdir(){
[[ -n "${__TEMPDIR__}" && -d "${__TEMPDIR__}" ]]\
&& rm -fr "${__TEMPDIR__}";
}
function set_tempdir(){
rm_tempdir;
while [[ -z "${__TEMPDIR__}" || -d "${__TEMPDIR__}" ]]; do
__TEMPDIR__="/tmp/${BASH_SOURCE[0]}_temp.${USER}.${RANDOM}";
done;
mkdir -p "${__TEMPDIR__}"
}
function teardown(){
# remove symlinks before files
local __DIR__="${__TEMPDIR__}/1234";
local __FILE__="test.sh";
local __DIR2__="${__TEMPDIR__}/12 34";
local __FILE2__="te st.sh";
[[ -e "${__DIR2__}" ]] && rm -rf "${__DIR2__:?}";
[[ -e "${__DIR__}/${__FILE2__}" ]] && rm -f "${__DIR__:?}/${__FILE2__}";
[[ -e "${__DIR2__}/${__FILE__}" ]] && rm -f "${__DIR2__:?}/${__FILE__}";
[[ -e "${__DIR2__}/${__FILE2__}" ]] && rm -f "${__DIR2__:?}/${__FILE2__}";
[[ -e ${__TEMPDIR__}/"${__FILE__}" ]] && rm -f "${__TEMPDIR__}/${__FILE__}";
[[ -e ${__TEMPDIR__}/current ]] && rm -rf "${__TEMPDIR__}/current";
[[ -e ${__TEMPDIR__}/current/loop ]] && rm -rf "${__TEMPDIR__}/current/loop";
[[ -e "${__DIR__}" ]] && rm -rf "${__DIR__:?}";
[[ -e "${__DIR__}/${__FILE__}" ]] && rm -f "${__DIR__:?}/${__FILE__}";
rm_tempdir;
}
function setup(){
set_tempdir;
local __DIR__="${__TEMPDIR__}/1234";
local __FILE__="test.sh";
local __DIR2__="${__TEMPDIR__}/12 34";
local __FILE2__="te st.sh";
mkdir "${__DIR__}"
touch "${__DIR__}/${__FILE__}"
ln -s "${__DIR__}/${__FILE__}" "${__TEMPDIR__}"
ln -s "${__DIR__}" "${__TEMPDIR__}/current"
ln -s "${__DIR__}" "${__TEMPDIR__}/current/loop"
mkdir "${__DIR2__}"
ln -s "${__DIR__}/${__FILE__}" "${__DIR__}/${__FILE2__}"
ln -s "${__DIR__}/${__FILE__}" "${__DIR2__}/${__FILE__}"
ln -s "${__DIR__}/${__FILE__}" "${__DIR2__}/${__FILE2__}"
}
function test1(){
echo 'Test 1: via dirname'
cat <<- EOF >"${__TEMPDIR__}/1234/test.sh"
echo \`dirname \$0\`
EOF
}
function test2(){
echo 'Test 2: via pwd'
cat <<- EOF >"${__TEMPDIR__}/1234/test.sh"
echo \$( cd "\$( dirname "\${BASH_SOURCE[0]}" )" && pwd )
EOF
}
function test3(){
echo 'Test 3: overcomplicated stackoverflow solution'
cat <<- EOF >"${__TEMPDIR__}/1234/test.sh"
__SOURCE__="\${BASH_SOURCE[0]}"
while [ -h "\$__SOURCE__" ]; do
__DIR__="\$( cd -P "\$( dirname "\$__SOURCE__" )" && pwd )"
__SOURCE__="\$(readlink "\$__SOURCE__" 2> /dev/null)"
[[ \$__SOURCE__ != /* ]] && __SOURCE__="\$__DIR__/\$__SOURCE__"
done
__DIR__="\$( cd -P "\$( dirname "\$__SOURCE__" )" && pwd )"
echo \$__DIR__
EOF
}
function test4(){
echo 'Test 4: via readlink'
cat <<- EOF >"${__TEMPDIR__}/1234/test.sh"
echo \`dirname \$(readlink -f \$0 2> /dev/null)\`
EOF
}
function test5(){
echo 'Test 5: via readlink with space'
cat <<- EOF >"${__TEMPDIR__}/1234/test.sh"
echo \`dirname \$(readlink -f "\$0" 2> /dev/null)\`
EOF
}
function test6(){
echo 'Test 6: as Test 2 but with cd -P';
cat <<- EOF >"${__TEMPDIR__}/1234/test.sh"
echo \$( cd -P "\$( dirname "\${BASH_SOURCE[0]}" )" && pwd )
EOF
}
function test7(){
echo 'Test 7: via cd -P and pwd, testing for symlinked file first';
cat <<- EOF >"${__TEMPDIR__}/1234/test.sh"
__SOURCE__="\${BASH_SOURCE[0]}"
while [[ -h "\${__SOURCE__}" ]]; do
__SOURCE__=\$(find "\${__SOURCE__}" -type l -ls | sed -n 's/^.* -> \(.*\)/\1/p');
done;
echo \$(cd -P "\$( dirname "\${__SOURCE__}" )" && pwd)
EOF
}
main(){
local __TEMPDIR__="";
echo;
teardown; # sanity check (in case last run was interrupted)
setup;
if [[ -n "${1}" ]]; then
"${1}" && testSuite;
else
test1 && testSuite;
test2 && testSuite;
test3 && testSuite;
test4 && testSuite;
test5 && testSuite;
test6 && testSuite;
test7 && testSuite;
fi
teardown;
}
main "$@";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment