Am 12.01.2013 14:53, schrieb Dan Douglas: > Yes some use -u / -e for debugging apparently. Actual logic relying upon > those > can be fragile of course. I prefer when things return nonzero instead of > throwing errors usually so that they're handleable. ah but you can still do that if you want
you just do ${unsetvar:-0} says you want 0 for null string or unset ${unsetvar-0} says you want 0 for unset. I know these aren't the sort of things you want to add retroactively, but if you program from the ground up with this in mind your code is much more explicit, and less reliant on particular interpreter behavior. So again it forces a more explicit programming style which is always better. Truthfully most people complain my scripts don't look like scripts any more but more like programs. But once they get used to the style most see its advantages. at teh very least when they have to figure out what is gone wrong they understand. regarding -e it mainly has a bad name because there is no good guide how to program with it. so for example this causes stress [ ! -d ${dirname} ] && mkdir ${dirname} because if the dir exists it will exit the scripts :) [ -d ${dirname} ] || mkdir ${dirname} this however is safe. actually forcing myself to work with SIGERR taught me a lot about how this sort of thing works. thats why I do for example use (old but simple example) set -o errtrace function TaceEvent { local LASTERR=$? local ETYPE="${1:?Missing Error Type}" PrintFunctionStack 1 cErrorOut 1 "${ETYPE} ${BASH_SOURCE[1]}(${BASH_LINENO[1]}):${FUNCNAME[1]} ELEVEL=${LASTERR} \"${BASH_COMMAND}\"" } trap 'TaceEvent ERR ' ERR which basically gives you a heads up everytime you haven't handled an error return code. so the following silly example test_func4() { false } test_func3() { test_func4 } test_func2() { test_func3 } test_func1() { test_func2 } test_func1 will give me a log that looks like #D: Sat Jan 12 15:49:13 CET 2013 : 18055 : test.sh (225 ) : main : "[5]/home/dethrophes/scripts/bash/test.sh(225):test_func1" #D: Sat Jan 12 15:49:13 CET 2013 : 18055 : test.sh (223 ) : test_func1 : "[4]/home/dethrophes/scripts/bash/test.sh(223):test_func2" #D: Sat Jan 12 15:49:13 CET 2013 : 18055 : test.sh (220 ) : test_func2 : "[3]/home/dethrophes/scripts/bash/test.sh(220):test_func3" #D: Sat Jan 12 15:49:13 CET 2013 : 18055 : test.sh (217 ) : test_func3 : "[2]/home/dethrophes/scripts/bash/test.sh(217):test_func4" #E: Sat Jan 12 15:49:13 CET 2013 : 18055 : test.sh (214 ) : test_func4 : "ERR /home/dethrophes/scripts/bash/test.sh(217):test_func4 ELEVEL=1 \"false\"" which allows me to very quickly route cause the error and fix it. if you really don't care you can just stick a ||true on the end to ignore it in the future. so in this case to something like test_func4() { false || true } I mean it would be nice to have an unset trap, but without it nounset is the next best thing. Also I don't think of this as debugging it's code verification/analysis. I do this so I don't have to debug my code. This is a big help against typos and scoping errors. like I say its like using lint.