= Bash Notes == basename Don't use `basename`, use: [,bash] ---- file=${path##*/} ---- == dirname Don't use `dirname`, use: [,bash] ---- dir=${path%/*} ---- == shopt If you set `shopt` in a function, reset to its default state with `trap`: [,bash] ---- func() { trap "$(shopt -p globstar)" RETURN shopt -q -s globstar } ---- == find, grep, print0, -0, -z Don't use `find` in `for` loops, because filenames can contain spaces. Try to use `globstar` and `nullglob` or null byte terminated strings. Instead of: [,bash] ---- func() { for file in $(find /usr/lib* -type f -name 'lib*.a' -print0 ); do echo $file done } ---- use: [,bash] ---- func() { trap "$(shopt -p nullglob globstar)" RETURN shopt -q -s nullglob globstar for file in /usr/lib*/**/lib*.a; do [[ -f $file ]] || continue echo "$file" done } ---- Or collect the filenames in an array, if you need them more than once: [,bash] ---- func() { trap "$(shopt -p globstar)" RETURN shopt -q -s globstar filenames=( /usr/lib*/**/lib*.a ) for file in "${filenames[@]}"; do [[ -f $file ]] || continue echo "$file" done } ---- Or, if you really want to use `find`, use `-print0` and an array: [,bash] ---- func() { mapfile -t -d '' filenames < <(find /usr/lib* -type f -name 'lib*.a' -print0) for file in "${filenames[@]}"; do echo "$file" done } ---- NOTE: `-d ''` is the same as `-d $'\0'` and sets the null byte as the delimiter. or: [,bash] ---- func() { find /usr/lib* -type f -name 'lib*.a' -print0 | while read -r -d '' file; do echo "$file" done } ---- or [,bash] ---- func() { while read -r -d '' file; do echo "$file" done < <(find /usr/lib* -type f -name 'lib*.a' -print0) } ---- Use the tool options for null terminated strings, like `-print0`, `-0`, `-z`, etc. == prefix or suffix array elements Instead of: [,bash] ---- func() { other-cmd $(for k in "$@"; do echo "prefix-$k"; done) } ---- do [,bash] ---- func() { other-cmd "${@/#/prefix-}" } ---- or suffix: [,bash] ---- func() { other-cmd "${@/%/-suffix}" } ---- == Join array elements with a separator char Here we have an associate array `_drivers`, where we want to print the keys separated by ',': [,bash] ---- if [[ ${!_drivers[*]} ]]; then echo "rd.driver.pre=$(IFS=, ;echo "${!_drivers[*]}")" > "${initdir}"/etc/cmdline.d/00-watchdog.conf fi ----