Last active
January 26, 2023 04:11
-
-
Save andrea-calligaris/04cfe28ca1068cfa5c82cdf4f3f68976 to your computer and use it in GitHub Desktop.
POSIX portable shell script with arguments [howto: shell script template]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/dash | |
# | |
# Template for shell scripts, with "help", both short and long options, | |
# and arguments. | |
# POSIX compliant, and following best practices. | |
# Distributed under WTFPL. | |
this_program_filename= | |
# Debug mode, true or false. | |
debug=true | |
# Options. | |
recursive=false | |
force=false | |
config_file= | |
verbose_level=0 | |
quit_with_usage_help() | |
{ | |
cat <<EOF | |
Usage: $this_program_filename [options] directory | |
Do something with DIRECTORY. | |
-r, --recursive recursively do stuff in all directories because yup; | |
also note the line break formatting and that | |
there's no period at the end of this sentence | |
-f, --force force execution even if the computer doesn't wanna | |
-c, --config FILE specify a configuration file to load | |
--verbose=LEVEL verbose level 0 to 2 (default 0, don't print anything); | |
also note: this option doesn't have the short form | |
It's a good idea to write here some more information about the script. Blah | |
blah blah; use the option --force (-f) only when you are angry. | |
The default configuration file is in /etc/path/... | |
To do X, you can use one of these commands: | |
$this_program_filename -r . | |
$this_program_filename ~ | |
However, if the program is very complex, make a man page for it. | |
Adapted from: <http://mywiki.wooledge.org/BashFAQ/035> | |
Interesting links: | |
<https://github.com/koalaman/shellcheck> | |
<https://stackoverflow.com/a/7948533> | |
<https://developer.ibm.com/tutorials/l-bash-parameters/> | |
EOF | |
# Good width limit is between 70 and 80 columns: --------------------|---------| | |
exit 0 | |
} | |
quit_with_error_msg() | |
{ | |
printf '%s: error: %s\n' "$this_program_filename" "$1" >&2 | |
printf 'Try "%s --help" for more information.\n' \ | |
"$this_program_filename" >&2 | |
exit 1 | |
} | |
# Get the program name preventing echoing of "./" when running directly. | |
this_program_filename=$( basename "$0" ) | |
# Parse options. | |
while :; do | |
case $1 in | |
# Good practice to have both '-h' and '--help'. | |
-h|--help) | |
quit_with_usage_help | |
;; | |
-r|--recursive) | |
recursive=true | |
;; | |
-f|--force) | |
force=true | |
;; | |
-c|--config) | |
if [ "$2" ]; then | |
config_file=$2 | |
shift | |
else | |
quit_with_error_msg \ | |
'--config option: missing argument.\n' | |
fi | |
;; | |
--verbose=?*) | |
# Delete everything up to "=" and assign the remainder. | |
verbose_level=${1#*=} | |
# Validate. | |
if [ -z "${verbose_level##*[!0-9]*}" ]; then | |
quit_with_error_msg \ | |
'--verbose option: expected a positive integer.' | |
fi | |
if [ "$verbose_level" -lt 0 ] || [ "$verbose_level" -gt 2 ] | |
then | |
quit_with_error_msg '--verbose option: out of range.' | |
fi | |
;; | |
# Handle the case of an empty argument ('--verbose='). | |
--verbose=) | |
quit_with_error_msg '--verbose option: missing argument.\n' | |
;; | |
# Double-dash: end of options. | |
--) | |
shift | |
break | |
;; | |
-?*) | |
err=$( printf 'invalid option "%s"\n' "$1" ) | |
quit_with_error_msg "$err" | |
;; | |
# Default case: no (more) options. | |
*) | |
break | |
esac | |
shift | |
done | |
# Print debug information. | |
if [ $debug = true ]; then | |
printf '## Debug info ##\n' | |
printf 'Variables dump (options should change these):\n' | |
printf ' > recursive: %s\n' "$recursive" | |
printf ' > force: %s\n' "$force" | |
printf ' > config_file: %s\n' "$config_file" | |
printf ' > verbose_level: %d\n' "$verbose_level" | |
if [ "$#" -eq 0 ]; then | |
printf 'No other arguments after the options.\n' | |
else | |
printf '%d argument(s) after the options:\n' $# | |
for var in "$@" | |
do | |
printf ' %s\n' "$var" | |
done | |
fi | |
printf '\n' | |
fi | |
# Check the parameters after the options. | |
if [ "$#" -eq 0 ]; then | |
quit_with_error_msg 'missing operand (the directory).' | |
elif [ "$#" -gt 1 ]; then | |
quit_with_error_msg 'too many parameters.' | |
fi | |
dir_to_process="$*" | |
if [ ! -d "$dir_to_process" ]; then | |
quit_with_error_msg 'No such file or directory.' | |
fi | |
# The rest of the code goes here... | |
dir_to_process=$( readlink -f "$dir_to_process" ) | |
ls -l "$dir_to_process" | |
# Etc. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/dash | |
clear | |
printf "\t\t ## Tests for the script ##" | |
executable="./shell_script_template" | |
separator="-------------------------------" | |
prompt=" > " | |
command="$executable" | |
printf "\n\n\n%s\n\n%s%s\n\n" "$separator" "$prompt" "$command" | |
$command | |
command="$executable --help" | |
printf "\n\n\n%s\n\n%s%s\n\n" "$separator" "$prompt" "$command" | |
$command | |
command="$executable /home" | |
printf "\n\n\n%s\n\n%s%s\n\n" "$separator" "$prompt" "$command" | |
$command | |
command="$executable -f" | |
printf "\n\n\n%s\n\n%s%s\n\n" "$separator" "$prompt" "$command" | |
$command | |
command="$executable -f -r" | |
printf "\n\n\n%s\n\n%s%s\n\n" "$separator" "$prompt" "$command" | |
$command | |
command="$executable -f /home -r" | |
printf "\n\n\n%s\n\n%s%s\n\n" "$separator" "$prompt" "$command" | |
$command | |
command="$executable -f /home" | |
printf "\n\n\n%s\n\n%s%s\n\n" "$separator" "$prompt" "$command" | |
$command | |
command="$executable -f --config my_configuration.cfg /home" | |
printf "\n\n\n%s\n\n%s%s\n\n" "$separator" "$prompt" "$command" | |
$command | |
command="$executable -f --config /home" | |
printf "\n\n\n%s\n\n%s%s\n\n" "$separator" "$prompt" "$command" | |
$command | |
command="$executable -f -c my_configuration.cfg -r /home" | |
printf "\n\n\n%s\n\n%s%s\n\n" "$separator" "$prompt" "$command" | |
$command | |
command="$executable -f -r --verbose=2 /home" | |
printf "\n\n\n%s\n\n%s%s\n\n" "$separator" "$prompt" "$command" | |
$command | |
command="$executable -f -r /home ." | |
printf "\n\n\n%s\n\n%s%s\n\n" "$separator" "$prompt" "$command" | |
$command | |
command="$executable -f -r ba be bi bo bu" | |
printf "\n\n\n%s\n\n%s%s\n\n" "$separator" "$prompt" "$command" | |
$command | |
# Etc. | |
printf "\n\n\n\n" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment