############################################################################### # Driglibash pack 1 # Usual helper functions for bash scripts # https://github.com/adrianamaglio/driglibash ############################################################################### # Set to true to make a pause at each step driglibash_step_by_step=false # Set to watever you want to have a prefix driglibash_section_prefix="" trap 'die "Received sigint"' INT # Output on standard error output yell() { echo >&2 -e "$@" } # Output first parameter, second parameter times repeat() { printf "$1"'%.s' $(eval "echo {1.."$(($2))"}") } # Output a "section title" to visually separate different script part # TODO local variables # TODO fixed place left aligned section(){ text="$driglibash_section_prefix$1" if [ -n "$text" ] ; then len="${#text}" max_len="$(($(tput cols)-2))" if [ "$len" -ge "$max_len" ] ; then right=5 left=5 else left="$((($max_len - $len)/2))" right="$left" fi else left=80 right=0 fi # If the character number was rounded down if [ "$(($left + $right + $len +1 ))" -eq "$max_len" ] ; then left="$(($left+ 1))" fi repeat '=' "$left" if [ "$right" -ge 1 ] ; then echo -n " $text " repeat '=' "$right" echo fi if "$driglibash_step_by_step" ; then echo "Press enter to proceed" read fi } alias step=section # Print an error, clean and exit die() { yell "$@" clean exit 1 } # Exit on error if not root root_or_die() { if [ "$UID" -ne 0 ] ; then die "You need to be root" fi } # Execute a command and die if it returns with error # run() { while true ; do "$@" code=$? if [ "$code" -ne 0 ] ; then yell "command [$*] failed with exit code '$code'" if [ -n "$driglibash_run_retry" ] ; then echo "Retry ? Retry (y), skip the command (s) or exit script(n) [Y/s/n] ?" read answer if [ "$answer" = "y" ] || [ "$answer" = "Y" ] || [ -z "$answer" ] ; then continue elif [ "$answer" = "s" ] || [ "$answer" = "S" ] ; then return "$code" fi fi die "Aborting" else break fi done } # Execute a commad in background and return its pid start(){ "$@" & pid=$! clean pre "kill $pid" return $pid } # Clean exit # # Record command lines passed as argument and execute them all when called without args # # One argument = One command # # TODO append or prepend according to arg declare -a driglibash_clean_actions clean() { if [ "$#" -eq 0 ] ; then echo "Cleaning" for action in "${driglibash_clean_actions[@]}" ; do echo "driglibash_clean> $action" $action done elif [ "$#" -eq 1 ] ; then driglibash_clean_actions+=("$1") elif [ "$#" -eq 2 ] ; then case "$1" in "pre") declare -a tmp tmp=("${driglibash_clean_actions[@]}") driglibash_clean_actions=("$2") driglibash_clean_actions+=("${tmp[@]}") ;; "post") driglibash_clean_actions+=("$2") ;; "del") for i in "${!driglibash_clean_actions[@]}" ; do if [ "$2" = "${driglibash_clean_actions[$i]}" ] ; then unset driglibash_clean_actions[$i] break fi done ;; *) die "driglibash_clean: action '$1' not supported" esac else die "driglibash_clean : Bad clean usage, receveid more than two args" fi } # tells where your executable is (absolute path). Follow simlinks if any argument provided where() { if [ -z "$1" ] ; then echo "$( cd -P "$( dirname "$1" )" && pwd )" else SOURCE="$0" while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" SOURCE="$(readlink "$SOURCE")" [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located done DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" echo $DIR fi } # Add the line $1 in file $2 if not present line_in_file() { if [ "$#" -ne 2 ] ; then die "Bad usage of 'line_in_file'. Got '$#' parameters : '$@'" ; fi if [ -z "$1" ] ; then die "Line arg is emtpy in 'line_in_file'" ; fi line="$1" if [ -z "$2" ] ; then die "File arg is emtpy in 'line_in_file'" ; fi file="$2" if [ ! -f "$file" ] ; then run touch "$file" ; fi grep -q -x -F "$line" "$file" || echo "$line" >> "$file" }