Everything in shell scripts should be a function
Everything in shell scripts should be built on top of functions. This will promote good coding practices and increase your scripts durability over time.
Example:
#!/bin/bash
foo() {
local VARIABLE=$1
eval echo $VARIABLE
}
main() {
foo "I like tacos!"
}
main
exit 0
Written by Richard Howard
Related protips
8 Responses
A related idiom that I like is python's use of if __name__ == "__main__":
...
This allows modules to be used as a library, instead of automatically executing code when you import (or source) that file. In shell scripts I do as you do, and encapsulate the program logic in functions, and then at the end of the script have:
if [[ "$(basename "$0" .sh)" == "MyScript" ]]; then
main
fi
the eval is a little difficult!
when passing elements that have to be "ran" by the script into a function you should use the 'eval' as it will ensure your code is treated as a unique shell call, thereby creating consistency in your scripts and predicability :)
There is literally no reason to do this for just about any shell script, especially not the eval bit. Functions are great, and use them, but no reason at all to mix patterns from other languages that have a real purpose for a main() function
# script pattern
foo() {}
bar() {}
# take some input, decide what to do with it
foo
Going to have to disagree with you on that.
here is why:
Most scripts encompass multiple actions. Organizing actions into a primary function makes code easier to read, understand and organize. Not to mention to allow for locally scoped variables by function . This thereby increases the maintainability of the script as requirements change.
edit:
I hate throwing away functionality I will need going forward. A well written script can be incorporated into other scripts if solid coding practices are adhered to.
I am all about GSD, but not at the longer term cost of avoidable technical debt
But how many shell scripts have truly reusable functionality? I am a firm believer in no abstraction until abstraction is needed. To me nothing should be written as if its a library until the second (even third) time you need to use it, that's how I GSD. For one thing, that gives you two use cases, instead of trying to imagine a second use case.
When I run into situations like this I write the "library" code in something else, something that's more portable and easier to maintain, then call its functionality from the script. Not only is it a faster script (evaluating a shell script isnt exactly fast) but its a good separation of concerns.
Don't get me wrong, I didn't mean to trash your tip. In essence I agree with you. Just there are limits to how much things should be abstracted, part of what makes scripting languages great is that they produce short and simple code to do one thing and one thing only.
I think MOST scripts have pieces of reusable functionality. think about all those shell scripts that use paths, permissions, etc. all of those are bits of code we re-use over and over again. I agree with "no abstraction until abstraction is needed" but for me and the things I use shell scripts for, I have many overlapping use cases. And I hate having to do it over and over again.
This tip is for those times other languages aren't available, or you cannot code what you need in the language that IS available (I do not code 'haskell' or 'Coffeescript' at this time for example, I am learning though!), not that what I do in those other languages is really MENT for systems management / basic systems tasks.
I do not think you are trashing anything, you bring up interesting points that are well worth discussing :)