summaryrefslogtreecommitdiffstats
path: root/docs/BASH.md
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 13:54:25 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 13:54:25 +0000
commit9cb1c4df7b9ce1a9ad1312621b0f2b16a94fba3a (patch)
tree2efb72864cc69e174c9c5ee33efb88a5f1553b48 /docs/BASH.md
parentInitial commit. (diff)
downloaddracut-9cb1c4df7b9ce1a9ad1312621b0f2b16a94fba3a.tar.xz
dracut-9cb1c4df7b9ce1a9ad1312621b0f2b16a94fba3a.zip
Adding upstream version 060+5.upstream/060+5
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'docs/BASH.md')
-rw-r--r--docs/BASH.md213
1 files changed, 213 insertions, 0 deletions
diff --git a/docs/BASH.md b/docs/BASH.md
new file mode 100644
index 0000000..e72a2f6
--- /dev/null
+++ b/docs/BASH.md
@@ -0,0 +1,213 @@
+# BASH Notes
+
+## basename
+Don't use `basename`, use:
+```shell
+ file=${path##*/}
+```
+
+## dirname
+Don't use `dirname`, use:
+```shell
+ dir=${path%/*}
+```
+
+## shopt
+If you set `shopt` in a function, reset to its default state with `trap`:
+```shell
+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:
+```shell
+func() {
+ for file in $(find /usr/lib* -type f -name 'lib*.a' -print0 ); do
+ echo $file
+ done
+}
+```
+
+use:
+```shell
+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:
+```shell
+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:
+```shell
+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:
+```shell
+func() {
+ find /usr/lib* -type f -name 'lib*.a' -print0 | while read -r -d '' file; do
+ echo "$file"
+ done
+}
+```
+
+or
+```shell
+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:
+```shell
+func() {
+ other-cmd $(for k in "$@"; do echo "prefix-$k"; done)
+}
+```
+do
+```shell
+func() {
+ other-cmd "${@/#/prefix-}"
+}
+```
+
+or suffix:
+```shell
+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 ',':
+```shell
+ if [[ ${!_drivers[*]} ]]; then
+ echo "rd.driver.pre=$(IFS=, ;echo "${!_drivers[*]}")" > "${initdir}"/etc/cmdline.d/00-watchdog.conf
+ fi
+```
+
+## Optional parameters to commands
+
+If you want to call a command `cmd` with an option, if a variable is set, rather than doing:
+
+```shell
+func() {
+ local param="$1"
+
+ if [[ $param ]]; then
+ param="--this-special-option $param"
+ fi
+
+ cmd $param
+}
+```
+
+do it like this:
+
+```shell
+func() {
+ local param="$1"
+
+ cmd ${param:+--this-special-option "$param"}
+}
+
+# cmd --this-special-option 'abc'
+func 'abc'
+
+# cmd
+func ''
+
+# cmd
+func
+```
+
+If you want to specify the option even with an empty string do this:
+
+```shell
+func() {
+ local -a special_params
+
+ if [[ ${1+_} ]]; then
+ # only declare `param` if $1 is set (even as null string)
+ local param="$1"
+ fi
+
+ # check if `param` is set (even as null string)
+ if [[ ${param+_} ]]; then
+ special_params=( --this-special-option "${param}" )
+ fi
+
+ cmd ${param+"${special_params[@]}"}
+}
+
+# cmd --this-special-option 'abc'
+func 'abc'
+
+# cmd --this-special-option ''
+func ''
+
+# cmd
+func
+```
+
+Or more simple, if you only have to set an option:
+```shell
+func() {
+ if [[ ${1+_} ]]; then
+ # only declare `param` if $1 is set (even as null string)
+ local param="$1"
+ fi
+
+ cmd ${param+--this-special-option}
+}
+
+# cmd --this-special-option
+func 'abc'
+
+# cmd --this-special-option
+func ''
+
+# cmd
+func
+```
+