├── README.md ├── template.sh └── utils.sh /README.md: -------------------------------------------------------------------------------- 1 | # bash-utils 2 | 3 | some utils for bash script. 4 | 5 | # intro 6 | 7 | I always use the bash as my devops script, while it's boring to write the condition judgement/echo statement/exit. 8 | 9 | So, I want to make the bash script short and clear. 10 | 11 | I have collected some useful functions into this repo, which save me a lot of time in the past few years. 12 | 13 | Just source the `utils.sh` and write the code calling the functions. 14 | 15 | You can just focus on the logical, not the bash syntax and expression 16 | 17 | # example 18 | 19 | ```bash 20 | echo_separator 21 | 22 | echo_step "1. begin to validate the params" 23 | 24 | if_empty_then_exit "$1" "the first param required!" 25 | FILE="${1}" 26 | if_path_not_exist_then_exit "${FILE}" "file not exist" 27 | 28 | VALUE=$(if_empty_return_default "${2}" 123) 29 | ``` 30 | 31 | # usage 32 | 33 | 34 | ```bash 35 | curl https://raw.githubusercontent.com/wklken/bash-utils/master/utils.sh > utils.sh && curl https://raw.githubusercontent.com/wklken/bash-utils/master/template.sh > run.sh 36 | ``` 37 | 38 | # Donation 39 | 40 | You can Buy me a coffee:) [link](http://www.wklken.me/pages/donation.html) 41 | 42 | 43 | # change log 44 | 45 | 2018-06-30 add some useful function from [pure-bash-bible](https://github.com/dylanaraps/pure-bash-bible) 46 | 47 | ------------------------ 48 | ------------------------ 49 | 50 | wklken 51 | 52 | Github: https://github.com/wklken 53 | 54 | Blog: [http://www.wklken.me](http://www.wklken.me) 55 | -------------------------------------------------------------------------------- /template.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # locate dir 4 | BASEDIR=$(dirname "$0") 5 | cd "$BASEDIR" || exit 6 | CURRENT_DIR=$(pwd) 7 | 8 | # source utils 9 | source "${CURRENT_DIR}"/utils.sh 10 | # do something 11 | 12 | -------------------------------------------------------------------------------- /utils.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # https://github.com/wklken/bash-utils 3 | 4 | #====================== echo ====================== 5 | 6 | echo_step() { 7 | # Usage: echo_step "1. this is the step 1" 8 | echo -e '\033[0;32m'"$1"'\033[0m' 9 | } 10 | 11 | echo_separator() { 12 | # Usage: echo_separator 13 | echo "====================================================" 14 | } 15 | 16 | echo_in_processing_bar() { 17 | # Usage: bar 1 10 18 | # ^----- Elapsed Percentage (0-100). 19 | # ^-- Total length in chars. 20 | ((elapsed=$1*$2/100)) 21 | 22 | # Create the bar with spaces. 23 | printf -v prog "%${elapsed}s" 24 | printf -v total "%$(($2-elapsed))s" 25 | 26 | printf '%s\r' "[${prog// /-}${total}]" 27 | } 28 | 29 | #====================== log ====================== 30 | 31 | log_info() { 32 | # Usage: log_info "this is the info log message" 33 | NOW=$(date +"%Y-%m-%d %H:%M:%S") 34 | echo "${NOW} [INFO] $1" 35 | } 36 | 37 | log_warnning() { 38 | # Usage: log_warnning "this is the warning log message" 39 | NOW=$(date +"%Y-%m-%d %H:%M:%S") 40 | echo "${NOW} [WARNNING] $1" 41 | } 42 | 43 | log_error() { 44 | # Usage: log_error "this is the error log message" 45 | NOW=$(date +"%Y-%m-%d %H:%M:%S") 46 | echo "${NOW} [ERROR] $1" 47 | } 48 | 49 | log_exit() { 50 | # Usage: log_exit "the log message before exit" 51 | log_error "$1" 52 | exit 1 53 | } 54 | 55 | #====================== action ====================== 56 | 57 | do_exit_0() { 58 | # Usage: do_exit_0 "the log message before exit 0" 59 | if [ ! -z "$1" ] 60 | then 61 | log_info "$1" 62 | fi 63 | exit 0 64 | } 65 | 66 | do_exit_1() { 67 | # Usage: do_exit_0 "the log message before exit 1" 68 | if [ ! -z "$1" ] 69 | then 70 | log_info "$1" 71 | fi 72 | exit 1 73 | } 74 | 75 | #====================== confirm====================== 76 | confirm() { 77 | # Usage: x=$(confirm "do you want to continue?") 78 | # if [ "$x" = "yes" ] 79 | QUESTION="$1" 80 | read -p "${QUESTION} [yN] " ANSWER 81 | if [[ "${ANSWER}" == "y" ]] || [[ "${ANSWER}" == "Y" ]] 82 | then 83 | echo "yes" 84 | else 85 | echo "no" 86 | fi 87 | } 88 | 89 | 90 | #====================== if ====================== 91 | 92 | #====================== if-then ====================== 93 | # exit 94 | if_error_then_exit() { 95 | # Usage: if_error_then_exit $? "fail, and exit" 96 | if [ "$1" -ne 0 ] 97 | then 98 | log_error "$2" 99 | exit 1 100 | fi 101 | } 102 | 103 | if_empty_then_exit() { 104 | # Usage: if_empty_then_exit ${1} "param 1 required" 105 | if [ -z "$1" ] 106 | then 107 | log_error "$2" 108 | exit 1 109 | fi 110 | } 111 | 112 | if_empty_then_return_default() { 113 | # Usage: A=$(if_empty_return_default "${1}" 123) 114 | if [ -z "${1}" ] 115 | then 116 | echo "${2}" 117 | else 118 | echo "${1}" 119 | fi 120 | } 121 | 122 | if_empty_then_log_warnning() { 123 | # Usage: if_empty_then_log_warnning "$1" "the param 1 is empty" 124 | if [ -z "${1}" ] 125 | then 126 | log_warnning "${2}" 127 | fi 128 | } 129 | 130 | if_path_not_exist_then_exit() { 131 | # Usage: if_path_not_exist_then_exit "/tmp/a.txt" "/tmp/a.txt is not exists" 132 | if [ ! -e "$1" ] 133 | then 134 | log_error "$2" 135 | exit 1 136 | fi 137 | } 138 | 139 | # action 140 | if_file_not_exist_then_touch() { 141 | # Usage: if_file_not_exist_then_touch "/tmp/a.txt" 142 | [ -e "$1" ] || touch "$1" 143 | return $? 144 | } 145 | if_dir_not_exist_then_mkdir() { 146 | # Usage: if_dir_not_exist_then_mkdir "/tmp/abc" 147 | [ -d "$1" ] || mkdir -p "$1" 148 | return $? 149 | } 150 | 151 | 152 | if_file_exist_then_remove() { 153 | # Usage: if_file_exist_then_remove "/tmp/a.txt" 154 | if [ -e "$1" ] 155 | then 156 | rm "$1" 157 | return $? 158 | fi 159 | } 160 | 161 | if_dir_exist_then_remove() { 162 | # Usage: if_dir_exist_then_remove "/tmp/abc" 163 | if [ -e "$1" ] 164 | then 165 | rm -rf "$1" 166 | return $? 167 | fi 168 | } 169 | 170 | function if_file_or_dir_exist_then_move_to() { 171 | if [ -e "$1" ] 172 | then 173 | mv "$1" "$2" 174 | return $? 175 | fi 176 | } 177 | 178 | function if_file_or_dir_exist_then_copy_to() { 179 | if [ -e "$1" ] 180 | then 181 | cp -r "$1" "$2" 182 | return $? 183 | fi 184 | } 185 | 186 | #====================== is ====================== 187 | 188 | is_command_exists () { 189 | type "$1" &> /dev/null ; 190 | } 191 | 192 | #====================== dir ====================== 193 | 194 | remkdir() { 195 | # Usage: remkdir "/tmp/abc" 196 | if [ -e "$1" ] 197 | then 198 | rm -rf "$1" 199 | local rc=$? 200 | if [ "$rc" -ne 0 ] 201 | then 202 | log_error "remkdir: fail, when do [rm -rf ${1}]" 203 | return "$rc" 204 | fi 205 | fi 206 | mkdir -p "$1" 207 | return $? 208 | } 209 | 210 | #====================== date ====================== 211 | get_today() { 212 | # Usage: x=$(get_today) 213 | echo "$(date +%Y%m%d)" 214 | } 215 | 216 | get_day_before_from_now() { 217 | # Usage: x=$(get_day_before_from_now 2) 218 | COUNT="$1" 219 | TODAY=$(date +%Y%m%d) 220 | echo $(date -d "$TODAY ${COUNT} days ago" +%Y%m%d) 221 | } 222 | 223 | get_day_before_from() { 224 | # Usage: y=$(get_day_before_from 20170905 2) 225 | FROM="$1" 226 | COUNT="$2" 227 | echo $(date -d "${FROM} ${COUNT} days ago" +%Y%m%d) 228 | } 229 | 230 | generate_date_list () { 231 | # Usage: generate_date_list 20120304 20120405 232 | TMP=$(date -d "$1" "+%Y%m%d") 233 | TO=$(date -d "$2" "+%Y%m%d") 234 | while [ "$(date -d $TO '+%s')" -ge "$(date -d $TMP '+%s')" ]; do 235 | echo $TMP 236 | TMP=$(date -d "$TMP 1day" "+%Y%m%d") 237 | done 238 | } 239 | 240 | #====================== tar ====================== 241 | do_tar() { 242 | # Usage: do_tar example.tar.gz example 243 | PKG_NAME="${1}" 244 | DIR="${2}" 245 | if_file_exist_then_remove "${PKG_NAME}" 246 | tar -czf "${PKG_NAME}" "${DIR}" 247 | if_error_then_exit "$?" "tar -czf ${PKG_NAME} ${DIR} fail" 248 | } 249 | 250 | #====================== string ====================== 251 | # reference https://github.com/dylanaraps/pure-bash-bible 252 | 253 | string_trim() { 254 | # Usage: string_trim " example string " 255 | : "${1#"${1%%[![:space:]]*}"}" 256 | : "${_%"${_##*[![:space:]]}"}" 257 | printf '%s\n' "$_" 258 | } 259 | 260 | string_split() { 261 | # Usage: string_split "string" "delimiter" 262 | IFS=$'\n' read -d "" -ra arr <<< "${1//$2/$'\n'}" 263 | printf '%s\n' "${arr[@]}" 264 | } 265 | 266 | string_lstrip() { 267 | # Usage: string_lstrip "string" "pattern" 268 | printf '%s\n' "${1##$2}" 269 | } 270 | 271 | string_rstrip() { 272 | # Usage: string_rstrip "string" "pattern" 273 | printf '%s\n' "${1%%$2}" 274 | } 275 | 276 | # Requires bash 4+ 277 | string_to_lower() { 278 | # Usage: string_to_lower "string" 279 | printf '%s\n' "${1,,}" 280 | } 281 | 282 | # Requires bash 4+ 283 | string_to_upper() { 284 | # Usage: string_to_upper "string" 285 | printf '%s\n' "${1^^}" 286 | } 287 | 288 | string_contains() { 289 | # Usage: string_contains hello he 290 | [[ "${1}" == *${2}* ]] 291 | } 292 | 293 | string_starts_with() { 294 | # Usage: string_starts_with hello he 295 | [[ "${1}" == ${2}* ]] 296 | } 297 | 298 | 299 | string_ends_with() { 300 | # Usage: string_ends_wit hello lo 301 | [[ "${1}" == *${2} ]] 302 | } 303 | 304 | 305 | string_regex() { 306 | # Usage: string_regex "string" "regex" 307 | [[ $1 =~ $2 ]] && printf '%s\n' "${BASH_REMATCH[1]}" 308 | } 309 | 310 | #====================== array ====================== 311 | # reference https://github.com/dylanaraps/pure-bash-bible 312 | array_reverse() { 313 | # Usage: array_reverse "array" 314 | shopt -s extdebug 315 | f()(printf '%s\n' "${BASH_ARGV[@]}"); f "$@" 316 | shopt -u extdebug 317 | } 318 | 319 | array_remove_dups() { 320 | # Usage: array_remove_dups "array" 321 | declare -A tmp_array 322 | 323 | for i in "$@"; do 324 | [[ "$i" ]] && IFS=" " tmp_array["${i:- }"]=1 325 | done 326 | 327 | printf '%s\n' "${!tmp_array[@]}" 328 | } 329 | 330 | array_random_element() { 331 | # Usage: array_random_element "array" 332 | local arr=("$@") 333 | printf '%s\n' "${arr[RANDOM % $#]}" 334 | } 335 | 336 | #====================== program ====================== 337 | 338 | run_command_in_background() { 339 | # Usage: run_command_in_background ./some_script.sh 340 | (nohup "$@" &>/dev/null &) 341 | } 342 | 343 | #====================== others ====================== 344 | generate_uuid() { 345 | # Usage: generate_uuid 346 | C="89ab" 347 | 348 | for ((N=0;N<16;++N)); do 349 | B="$((RANDOM%256))" 350 | 351 | case "$N" in 352 | 6) printf '4%x' "$((B%16))" ;; 353 | 8) printf '%c%x' "${C:$RANDOM%${#C}:1}" "$((B%16))" ;; 354 | 355 | 3|5|7|9) 356 | printf '%02x-' "$B" 357 | ;; 358 | 359 | *) 360 | printf '%02x' "$B" 361 | ;; 362 | esac 363 | done 364 | 365 | printf '\n' 366 | } 367 | --------------------------------------------------------------------------------