Harald Hoyer
3 years ago
committed by
Harald Hoyer
1 changed files with 213 additions and 0 deletions
@ -0,0 +1,213 @@
@@ -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 nullglob globstar)" RETURN |
||||
shopt -q -s nullglob 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 nullglob globstar)" RETURN |
||||
shopt -q -s nullglob 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 |
||||
``` |
||||
|
Loading…
Reference in new issue