mirror of
https://github.com/dylanaraps/pure-bash-bible.git
synced 2025-01-17 04:08:17 +01:00
Added conditionals
This commit is contained in:
parent
c4a203bb40
commit
f1e18e8bd8
@ -17,3 +17,4 @@ chapter15.txt
|
||||
chapter16.txt
|
||||
chapter17.txt
|
||||
chapter18.txt
|
||||
chapter19.txt
|
||||
|
@ -1,58 +1,59 @@
|
||||
|
||||
# ARITHMETIC OPERATORS
|
||||
# CONDITIONAL EXPRESSIONS
|
||||
|
||||
## Assignment
|
||||
## File Conditionals
|
||||
|
||||
| Operators | What does it do? |
|
||||
| --------- | ---------------- |
|
||||
| `=` | Initialize or change the value of a variable.
|
||||
| Expression | Value | What does it do? |
|
||||
| ---------- | ------ | ---------------- |
|
||||
| `-a` | `file` | If file exists.
|
||||
| `-b` | `file` | If file exists and is a block special file.
|
||||
| `-c` | `file` | If file exists and is a character special file.
|
||||
| `-d` | `file` | If file exists and is a directory.
|
||||
| `-e` | `file` | If file exists.
|
||||
| `-f` | `file` | If file exists and is a regular file.
|
||||
| `-g` | `file` | If file exists and its set-group-id bit is set.
|
||||
| `-h` | `file` | If file exists and is a symbolic link.
|
||||
| `-k` | `file` | If file exists and its sticky-bit is set
|
||||
| `-p` | `file` | If file exists and is a named pipe (*FIFO*).
|
||||
| `-r` | `file` | If file exists and is readable.
|
||||
| `-s` | `file` | If file exists and its size is greater than zero.
|
||||
| `-t` | `fd` | If file descriptor is open and refers to a terminal.
|
||||
| `-u` | `file` | If file exists and its set-user-id bit is set.
|
||||
| `-w` | `file` | If file exists and is writable.
|
||||
| `-x` | `file` | If file exists and is executable.
|
||||
| `-G` | `file` | If file exists and is owned by the effective group ID.
|
||||
| `-L` | `file` | If file exists and is a symbolic link.
|
||||
| `-N` | `file` | If file exists and has been modified since last read.
|
||||
| `-O` | `file` | If file exists and is owned by the effective user ID.
|
||||
| `-S` | `file` | If file exists and is a socket.
|
||||
|
||||
## Arithmetic
|
||||
## File Comparisons
|
||||
|
||||
| Operators | What does it do? |
|
||||
| --------- | ---------------- |
|
||||
| `+` | Addition
|
||||
| `-` | Subtraction
|
||||
| `*` | Multiplication
|
||||
| `/` | Division
|
||||
| `**` | Exponentiation
|
||||
| `%` | Modulo
|
||||
| `+=` | Plus-Equal (*Increment a variable.*)
|
||||
| `-=` | Minus-Equal (*Decrement a variable.*)
|
||||
| `*=` | Times-Equal (*Multiply a variable.*)
|
||||
| `/=` | Slash-Equal (*Divide a variable.*)
|
||||
| `%=` | Mod-Equal (*Remainder of dividing a variable.*)
|
||||
| Expression | What does it do? |
|
||||
| ---------- | ---------------- |
|
||||
| `file -ef file2` | If both files refer to the same inode and device numbers.
|
||||
| `file -nt file2` | If `file` is newer than `file2` (*uses modification ime*) or `file` exists and `file2` does not.
|
||||
| `file -ot file2` | If `file` is older than `file2` (*uses modification ime*) or `file2` exists and `file` does not.
|
||||
|
||||
## Bitwise
|
||||
## Variable Conditionals
|
||||
|
||||
| Operators | What does it do? |
|
||||
| --------- | ---------------- |
|
||||
| `<<` | Bitwise Left Shift
|
||||
| `<<=` | Left-Shift-Equal
|
||||
| `>>` | Bitwise Right Shift
|
||||
| `>>=` | Right-Shift-Equal
|
||||
| `&` | Bitwise AND
|
||||
| `&=` | Bitwise AND-Equal
|
||||
| `\|` | Bitwise OR
|
||||
| `\|=` | Bitwise OR-Equal
|
||||
| `~` | Bitwise NOT
|
||||
| `^` | Bitwise XOR
|
||||
| `^=` | Bitwise XOR-Equal
|
||||
| Expression | Value | What does it do? |
|
||||
| ---------- | ----- | ---------------- |
|
||||
| `-o` | `opt` | If shell option is enabled.
|
||||
| `-v` | `var` | If variable has a value assigned.
|
||||
| `-R` | `var` | If variable is a name reference.
|
||||
| `-z` | `var` | If the length of string is zero.
|
||||
| `-n` | `var` | If the length of string is non-zero.
|
||||
|
||||
## Logical
|
||||
|
||||
| Operators | What does it do? |
|
||||
| --------- | ---------------- |
|
||||
| `!` | NOT
|
||||
| `&&` | AND
|
||||
| `\|\|` | OR
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
| Operators | What does it do? | Example |
|
||||
| --------- | ---------------- | ------- |
|
||||
| `,` | Comma Separator | `((a=1,b=2,c=3))`
|
||||
## Variable Comparisons
|
||||
|
||||
| Expression | What does it do? |
|
||||
| ---------- | ---------------- |
|
||||
| `var = var2` | Equal to.
|
||||
| `var == var2` | Equal to (*synonym for `=`*).
|
||||
| `var != var2` | Not equal to.
|
||||
| `var < var2` | Less than (*in ASCII alphabetical order.*)
|
||||
| `var > var2` | Greater than (*in ASCII alphabetical order.*)
|
||||
|
||||
<!-- CHAPTER END -->
|
||||
|
||||
|
@ -1,31 +1,58 @@
|
||||
# ARITHMETIC
|
||||
|
||||
## Simpler syntax to set variables
|
||||
# ARITHMETIC OPERATORS
|
||||
|
||||
```shell
|
||||
# Simple math
|
||||
((var=1+2))
|
||||
## Assignment
|
||||
|
||||
# Decrement/Increment variable
|
||||
((var++))
|
||||
((var--))
|
||||
((var+=1))
|
||||
((var-=1))
|
||||
| Operators | What does it do? |
|
||||
| --------- | ---------------- |
|
||||
| `=` | Initialize or change the value of a variable.
|
||||
|
||||
# Using variables
|
||||
((var=var2*arr[2]))
|
||||
```
|
||||
## Arithmetic
|
||||
|
||||
## Ternary Tests
|
||||
| Operators | What does it do? |
|
||||
| --------- | ---------------- |
|
||||
| `+` | Addition
|
||||
| `-` | Subtraction
|
||||
| `*` | Multiplication
|
||||
| `/` | Division
|
||||
| `**` | Exponentiation
|
||||
| `%` | Modulo
|
||||
| `+=` | Plus-Equal (*Increment a variable.*)
|
||||
| `-=` | Minus-Equal (*Decrement a variable.*)
|
||||
| `*=` | Times-Equal (*Multiply a variable.*)
|
||||
| `/=` | Slash-Equal (*Divide a variable.*)
|
||||
| `%=` | Mod-Equal (*Remainder of dividing a variable.*)
|
||||
|
||||
## Bitwise
|
||||
|
||||
| Operators | What does it do? |
|
||||
| --------- | ---------------- |
|
||||
| `<<` | Bitwise Left Shift
|
||||
| `<<=` | Left-Shift-Equal
|
||||
| `>>` | Bitwise Right Shift
|
||||
| `>>=` | Right-Shift-Equal
|
||||
| `&` | Bitwise AND
|
||||
| `&=` | Bitwise AND-Equal
|
||||
| `\|` | Bitwise OR
|
||||
| `\|=` | Bitwise OR-Equal
|
||||
| `~` | Bitwise NOT
|
||||
| `^` | Bitwise XOR
|
||||
| `^=` | Bitwise XOR-Equal
|
||||
|
||||
## Logical
|
||||
|
||||
| Operators | What does it do? |
|
||||
| --------- | ---------------- |
|
||||
| `!` | NOT
|
||||
| `&&` | AND
|
||||
| `\|\|` | OR
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
| Operators | What does it do? | Example |
|
||||
| --------- | ---------------- | ------- |
|
||||
| `,` | Comma Separator | `((a=1,b=2,c=3))`
|
||||
|
||||
```shell
|
||||
# Set the value of var to var2 if var2 is greater than var.
|
||||
# var: variable to set.
|
||||
# var2>var: Condition to test.
|
||||
# ?var2: If the test succeeds.
|
||||
# :var: If the test fails.
|
||||
((var=var2>var?var2:var))
|
||||
```
|
||||
|
||||
<!-- CHAPTER END -->
|
||||
|
||||
|
@ -1,42 +1,30 @@
|
||||
# TRAPS
|
||||
# ARITHMETIC
|
||||
|
||||
Traps allow a script to execute code on various signals. In [pxltrm](https://github.com/dylanaraps/pxltrm) (*a pixel art editor written in bash*) traps are used to redraw the user interface on window resize. Another use case is cleaning up temporary files on script exit.
|
||||
|
||||
Traps should be added near the start of scripts so any early errors are also caught.
|
||||
|
||||
**NOTE:** For a full list of signals, see `trap -l`.
|
||||
|
||||
|
||||
## Do something on script exit
|
||||
## Simpler syntax to set variables
|
||||
|
||||
```shell
|
||||
# Clear screen on script exit.
|
||||
trap 'printf \\e[2J\\e[H\\e[m' EXIT
|
||||
# Simple math
|
||||
((var=1+2))
|
||||
|
||||
# Decrement/Increment variable
|
||||
((var++))
|
||||
((var--))
|
||||
((var+=1))
|
||||
((var-=1))
|
||||
|
||||
# Using variables
|
||||
((var=var2*arr[2]))
|
||||
```
|
||||
|
||||
## Ignore terminal interrupt (CTRL+C, SIGINT)
|
||||
## Ternary Tests
|
||||
|
||||
```shell
|
||||
trap '' INT
|
||||
```
|
||||
|
||||
## React to window resize
|
||||
|
||||
```shell
|
||||
# Call a function on window resize.
|
||||
trap 'code_here' SIGWINCH
|
||||
```
|
||||
|
||||
## Do something before every command
|
||||
|
||||
```shell
|
||||
trap 'code_here' DEBUG
|
||||
```
|
||||
|
||||
## Do something when a shell function or a sourced file finishes executing
|
||||
|
||||
```shell
|
||||
trap 'code_here' RETURN
|
||||
# Set the value of var to var2 if var2 is greater than var.
|
||||
# var: variable to set.
|
||||
# var2>var: Condition to test.
|
||||
# ?var2: If the test succeeds.
|
||||
# :var: If the test fails.
|
||||
((var=var2>var?var2:var))
|
||||
```
|
||||
|
||||
<!-- CHAPTER END -->
|
||||
|
@ -1,13 +1,42 @@
|
||||
# PERFORMANCE
|
||||
# TRAPS
|
||||
|
||||
## Disable Unicode
|
||||
Traps allow a script to execute code on various signals. In [pxltrm](https://github.com/dylanaraps/pxltrm) (*a pixel art editor written in bash*) traps are used to redraw the user interface on window resize. Another use case is cleaning up temporary files on script exit.
|
||||
|
||||
If unicode is not required, it can be disabled for a performance increase. Results may vary however there have been noticeable improvements in [neofetch](https://github.com/dylanaraps/neofetch) and other programs.
|
||||
Traps should be added near the start of scripts so any early errors are also caught.
|
||||
|
||||
**NOTE:** For a full list of signals, see `trap -l`.
|
||||
|
||||
|
||||
## Do something on script exit
|
||||
|
||||
```shell
|
||||
# Disable unicode.
|
||||
LC_ALL=C
|
||||
LANG=C
|
||||
# Clear screen on script exit.
|
||||
trap 'printf \\e[2J\\e[H\\e[m' EXIT
|
||||
```
|
||||
|
||||
## Ignore terminal interrupt (CTRL+C, SIGINT)
|
||||
|
||||
```shell
|
||||
trap '' INT
|
||||
```
|
||||
|
||||
## React to window resize
|
||||
|
||||
```shell
|
||||
# Call a function on window resize.
|
||||
trap 'code_here' SIGWINCH
|
||||
```
|
||||
|
||||
## Do something before every command
|
||||
|
||||
```shell
|
||||
trap 'code_here' DEBUG
|
||||
```
|
||||
|
||||
## Do something when a shell function or a sourced file finishes executing
|
||||
|
||||
```shell
|
||||
trap 'code_here' RETURN
|
||||
```
|
||||
|
||||
<!-- CHAPTER END -->
|
||||
|
@ -1,51 +1,13 @@
|
||||
# OBSOLETE SYNTAX
|
||||
# PERFORMANCE
|
||||
|
||||
## Shebang
|
||||
## Disable Unicode
|
||||
|
||||
Use `#!/usr/bin/env bash` instead of `#!/bin/bash`.
|
||||
|
||||
- The former searches the user's `PATH` to find the `bash` binary.
|
||||
- The latter assumes it is always installed to `/bin/` which can cause issues.
|
||||
If unicode is not required, it can be disabled for a performance increase. Results may vary however there have been noticeable improvements in [neofetch](https://github.com/dylanaraps/neofetch) and other programs.
|
||||
|
||||
```shell
|
||||
# Right:
|
||||
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Wrong:
|
||||
|
||||
#!/bin/bash
|
||||
```
|
||||
|
||||
## Command Substitution
|
||||
|
||||
Use `$()` instead of `` ` ` ``.
|
||||
|
||||
```shell
|
||||
# Right.
|
||||
var="$(command)"
|
||||
|
||||
# Wrong.
|
||||
var=`command`
|
||||
|
||||
# $() can easily be nested whereas `` cannot.
|
||||
var="$(command "$(command)")"
|
||||
```
|
||||
|
||||
## Function Declaration
|
||||
|
||||
Do not use the `function` keyword, it reduces compatibility with older versions of `bash`.
|
||||
|
||||
```shell
|
||||
# Right.
|
||||
do_something() {
|
||||
# ...
|
||||
}
|
||||
|
||||
# Wrong.
|
||||
function do_something() {
|
||||
# ...
|
||||
}
|
||||
# Disable unicode.
|
||||
LC_ALL=C
|
||||
LANG=C
|
||||
```
|
||||
|
||||
<!-- CHAPTER END -->
|
||||
|
@ -1,93 +1,51 @@
|
||||
# INTERNAL VARIABLES
|
||||
# OBSOLETE SYNTAX
|
||||
|
||||
## Get the location to the `bash` binary
|
||||
## Shebang
|
||||
|
||||
Use `#!/usr/bin/env bash` instead of `#!/bin/bash`.
|
||||
|
||||
- The former searches the user's `PATH` to find the `bash` binary.
|
||||
- The latter assumes it is always installed to `/bin/` which can cause issues.
|
||||
|
||||
```shell
|
||||
"$BASH"
|
||||
# Right:
|
||||
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Wrong:
|
||||
|
||||
#!/bin/bash
|
||||
```
|
||||
|
||||
## Get the version of the current running `bash` process
|
||||
## Command Substitution
|
||||
|
||||
Use `$()` instead of `` ` ` ``.
|
||||
|
||||
```shell
|
||||
# As a string.
|
||||
"$BASH_VERSION"
|
||||
# Right.
|
||||
var="$(command)"
|
||||
|
||||
# As an array.
|
||||
"${BASH_VERSINFO[@]}"
|
||||
# Wrong.
|
||||
var=`command`
|
||||
|
||||
# $() can easily be nested whereas `` cannot.
|
||||
var="$(command "$(command)")"
|
||||
```
|
||||
|
||||
## Open the user's preferred text editor
|
||||
## Function Declaration
|
||||
|
||||
Do not use the `function` keyword, it reduces compatibility with older versions of `bash`.
|
||||
|
||||
```shell
|
||||
"$EDITOR" "$file"
|
||||
# Right.
|
||||
do_something() {
|
||||
# ...
|
||||
}
|
||||
|
||||
# NOTE: This variable may be empty, set a fallback value.
|
||||
"${EDITOR:-vi}" "$file"
|
||||
```
|
||||
|
||||
## Get the name of the current function
|
||||
|
||||
```shell
|
||||
# Current function.
|
||||
"${FUNCNAME[0]}"
|
||||
|
||||
# Parent function.
|
||||
"${FUNCNAME[1]}"
|
||||
|
||||
# So on and so forth.
|
||||
"${FUNCNAME[2]}"
|
||||
"${FUNCNAME[3]}"
|
||||
|
||||
# All functions including parents.
|
||||
"${FUNCNAME[@]}"
|
||||
```
|
||||
|
||||
## Get the host-name of the system
|
||||
|
||||
```shell
|
||||
"$HOSTNAME"
|
||||
|
||||
# NOTE: This variable may be empty.
|
||||
# Optionally set a fallback to the hostname command.
|
||||
"${HOSTNAME:-$(hostname)}"
|
||||
```
|
||||
|
||||
## Get the architecture of the Operating System
|
||||
|
||||
```shell
|
||||
"$HOSTTYPE"
|
||||
```
|
||||
|
||||
## Get the name of the Operating System / Kernel
|
||||
|
||||
This can be used to add conditional support for different Operating
|
||||
Systems without needing to call `uname`.
|
||||
|
||||
```shell
|
||||
"$OSTYPE"
|
||||
```
|
||||
|
||||
## Get the current working directory
|
||||
|
||||
This is an alternative to the `pwd` built-in.
|
||||
|
||||
```shell
|
||||
"$PWD"
|
||||
```
|
||||
|
||||
## Get the number of seconds the script has been running
|
||||
|
||||
```shell
|
||||
"$SECONDS"
|
||||
```
|
||||
|
||||
## Get a pseudorandom integer
|
||||
|
||||
Each time `$RANDOM` is used, a different integer between `0` and `32767` is returned. This variable should not be used for anything related to security (*this includes encryption keys etc*).
|
||||
|
||||
|
||||
```shell
|
||||
"$RANDOM"
|
||||
# Wrong.
|
||||
function do_something() {
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
<!-- CHAPTER END -->
|
||||
|
@ -1,78 +1,93 @@
|
||||
# INFORMATION ABOUT THE TERMINAL
|
||||
# INTERNAL VARIABLES
|
||||
|
||||
## Get the terminal size in lines and columns (*from a script*)
|
||||
|
||||
This is handy when writing scripts in pure bash and `stty`/`tput` can’t be
|
||||
called.
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
get_term_size() {
|
||||
# Usage: get_term_size
|
||||
|
||||
# (:;:) is a micro sleep to ensure the variables are
|
||||
# exported immediately.
|
||||
shopt -s checkwinsize; (:;:)
|
||||
printf '%s\n' "$LINES $COLUMNS"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
## Get the location to the `bash` binary
|
||||
|
||||
```shell
|
||||
# Output: LINES COLUMNS
|
||||
$ get_term_size
|
||||
15 55
|
||||
"$BASH"
|
||||
```
|
||||
|
||||
## Get the terminal size in pixels
|
||||
|
||||
**CAVEAT**: This does not work in some terminal emulators.
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
get_window_size() {
|
||||
# Usage: get_window_size
|
||||
printf '%b' "${TMUX:+\\ePtmux;\\e}\\e[14t${TMUX:+\\e\\\\}"
|
||||
IFS=';t' read -d t -t 0.05 -sra term_size
|
||||
printf '%s\n' "${term_size[1]}x${term_size[2]}"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
## Get the version of the current running `bash` process
|
||||
|
||||
```shell
|
||||
# Output: WIDTHxHEIGHT
|
||||
$ get_window_size
|
||||
1200x800
|
||||
# As a string.
|
||||
"$BASH_VERSION"
|
||||
|
||||
# Output (fail):
|
||||
$ get_window_size
|
||||
x
|
||||
# As an array.
|
||||
"${BASH_VERSINFO[@]}"
|
||||
```
|
||||
|
||||
## Get the current cursor position
|
||||
|
||||
This is useful when creating a TUI in pure bash.
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
get_cursor_pos() {
|
||||
# Usage: get_cursor_pos
|
||||
IFS='[;' read -p $'\e[6n' -d R -rs _ y x _
|
||||
printf '%s\n' "$x $y"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
## Open the user's preferred text editor
|
||||
|
||||
```shell
|
||||
# Output: X Y
|
||||
$ get_cursor_pos
|
||||
1 8
|
||||
"$EDITOR" "$file"
|
||||
|
||||
# NOTE: This variable may be empty, set a fallback value.
|
||||
"${EDITOR:-vi}" "$file"
|
||||
```
|
||||
|
||||
## Get the name of the current function
|
||||
|
||||
```shell
|
||||
# Current function.
|
||||
"${FUNCNAME[0]}"
|
||||
|
||||
# Parent function.
|
||||
"${FUNCNAME[1]}"
|
||||
|
||||
# So on and so forth.
|
||||
"${FUNCNAME[2]}"
|
||||
"${FUNCNAME[3]}"
|
||||
|
||||
# All functions including parents.
|
||||
"${FUNCNAME[@]}"
|
||||
```
|
||||
|
||||
## Get the host-name of the system
|
||||
|
||||
```shell
|
||||
"$HOSTNAME"
|
||||
|
||||
# NOTE: This variable may be empty.
|
||||
# Optionally set a fallback to the hostname command.
|
||||
"${HOSTNAME:-$(hostname)}"
|
||||
```
|
||||
|
||||
## Get the architecture of the Operating System
|
||||
|
||||
```shell
|
||||
"$HOSTTYPE"
|
||||
```
|
||||
|
||||
## Get the name of the Operating System / Kernel
|
||||
|
||||
This can be used to add conditional support for different Operating
|
||||
Systems without needing to call `uname`.
|
||||
|
||||
```shell
|
||||
"$OSTYPE"
|
||||
```
|
||||
|
||||
## Get the current working directory
|
||||
|
||||
This is an alternative to the `pwd` built-in.
|
||||
|
||||
```shell
|
||||
"$PWD"
|
||||
```
|
||||
|
||||
## Get the number of seconds the script has been running
|
||||
|
||||
```shell
|
||||
"$SECONDS"
|
||||
```
|
||||
|
||||
## Get a pseudorandom integer
|
||||
|
||||
Each time `$RANDOM` is used, a different integer between `0` and `32767` is returned. This variable should not be used for anything related to security (*this includes encryption keys etc*).
|
||||
|
||||
|
||||
```shell
|
||||
"$RANDOM"
|
||||
```
|
||||
|
||||
<!-- CHAPTER END -->
|
||||
|
@ -1,145 +1,78 @@
|
||||
# CONVERSION
|
||||
# INFORMATION ABOUT THE TERMINAL
|
||||
|
||||
## Convert a hex color to RGB
|
||||
## Get the terminal size in lines and columns (*from a script*)
|
||||
|
||||
This is handy when writing scripts in pure bash and `stty`/`tput` can’t be
|
||||
called.
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
hex_to_rgb() {
|
||||
# Usage: hex_to_rgb "#FFFFFF"
|
||||
: "${1/\#}"
|
||||
((r=16#${_:0:2},g=16#${_:2:2},b=16#${_:4:2}))
|
||||
printf '%s\n' "$r $g $b"
|
||||
get_term_size() {
|
||||
# Usage: get_term_size
|
||||
|
||||
# (:;:) is a micro sleep to ensure the variables are
|
||||
# exported immediately.
|
||||
shopt -s checkwinsize; (:;:)
|
||||
printf '%s\n' "$LINES $COLUMNS"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
$ hex_to_rgb "#FFFFFF"
|
||||
255 255 255
|
||||
# Output: LINES COLUMNS
|
||||
$ get_term_size
|
||||
15 55
|
||||
```
|
||||
|
||||
## Get the terminal size in pixels
|
||||
|
||||
## Convert an RGB color to hex
|
||||
**CAVEAT**: This does not work in some terminal emulators.
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
rgb_to_hex() {
|
||||
# Usage: rgb_to_hex "r" "g" "b"
|
||||
printf '#%02x%02x%02x\n' "$1" "$2" "$3"
|
||||
get_window_size() {
|
||||
# Usage: get_window_size
|
||||
printf '%b' "${TMUX:+\\ePtmux;\\e}\\e[14t${TMUX:+\\e\\\\}"
|
||||
IFS=';t' read -d t -t 0.05 -sra term_size
|
||||
printf '%s\n' "${term_size[1]}x${term_size[2]}"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
$ rgb_to_hex "255" "255" "255"
|
||||
#FFFFFF
|
||||
# Output: WIDTHxHEIGHT
|
||||
$ get_window_size
|
||||
1200x800
|
||||
|
||||
# Output (fail):
|
||||
$ get_window_size
|
||||
x
|
||||
```
|
||||
|
||||
## Get the current cursor position
|
||||
|
||||
# CODE GOLF
|
||||
This is useful when creating a TUI in pure bash.
|
||||
|
||||
## Shorter `for` loop syntax
|
||||
**Example Function:**
|
||||
|
||||
```shell
|
||||
# Tiny C Style.
|
||||
for((;i++<10;)){ echo "$i";}
|
||||
|
||||
# Undocumented method.
|
||||
for i in {1..10};{ echo "$i";}
|
||||
|
||||
# Expansion.
|
||||
for i in {1..10}; do echo "$i"; done
|
||||
|
||||
# C Style.
|
||||
for((i=0;i<=10;i++)); do echo "$i"; done
|
||||
```
|
||||
|
||||
## Shorter infinite loops
|
||||
|
||||
```shell
|
||||
# Normal method
|
||||
while :; do echo hi; done
|
||||
|
||||
# Shorter
|
||||
for((;;)){ echo hi;}
|
||||
```
|
||||
|
||||
## Shorter function declaration
|
||||
|
||||
```shell
|
||||
# Normal method
|
||||
f(){ echo hi;}
|
||||
|
||||
# Using a subshell
|
||||
f()(echo hi)
|
||||
|
||||
# Using arithmetic
|
||||
# This can be used to assign integer values.
|
||||
# Example: f a=1
|
||||
# f a++
|
||||
f()(($1))
|
||||
|
||||
# Using tests, loops etc.
|
||||
# NOTE: ‘while’, ‘until’, ‘case’, ‘(())’, ‘[[]]’ can also be used.
|
||||
f()if true; then echo "$1"; fi
|
||||
f()for i in "$@"; do echo "$i"; done
|
||||
```
|
||||
|
||||
## Shorter `if` syntax
|
||||
|
||||
```shell
|
||||
# One line
|
||||
# Note: The 3rd statement may run when the 1st is true
|
||||
[[ "$var" == hello ]] && echo hi || echo bye
|
||||
[[ "$var" == hello ]] && { echo hi; echo there; } || echo bye
|
||||
|
||||
# Multi line (no else, single statement)
|
||||
# Note: The exit status may not be the same as with an if statement
|
||||
[[ "$var" == hello ]] && \
|
||||
echo hi
|
||||
|
||||
# Multi line (no else)
|
||||
[[ "$var" == hello ]] && {
|
||||
echo hi
|
||||
# ...
|
||||
```sh
|
||||
get_cursor_pos() {
|
||||
# Usage: get_cursor_pos
|
||||
IFS='[;' read -p $'\e[6n' -d R -rs _ y x _
|
||||
printf '%s\n' "$x $y"
|
||||
}
|
||||
```
|
||||
|
||||
## Simpler `case` statement to set variable
|
||||
|
||||
The `:` built-in can be used to avoid repeating `variable=` in a case statement. The `$_` variable stores the last argument of the last command. `:` always succeeds so it can be used to store the variable value.
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
# Modified snippet from Neofetch.
|
||||
case "$OSTYPE" in
|
||||
"darwin"*)
|
||||
: "MacOS"
|
||||
;;
|
||||
|
||||
"linux"*)
|
||||
: "Linux"
|
||||
;;
|
||||
|
||||
*"bsd"* | "dragonfly" | "bitrig")
|
||||
: "BSD"
|
||||
;;
|
||||
|
||||
"cygwin" | "msys" | "win32")
|
||||
: "Windows"
|
||||
;;
|
||||
|
||||
*)
|
||||
printf '%s\n' "Unknown OS detected, aborting..." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Finally, set the variable.
|
||||
os="$_"
|
||||
# Output: X Y
|
||||
$ get_cursor_pos
|
||||
1 8
|
||||
```
|
||||
|
||||
<!-- CHAPTER END -->
|
||||
|
@ -1,189 +1,146 @@
|
||||
# OTHER
|
||||
# CONVERSION
|
||||
|
||||
## Use `read` as an alternative to the `sleep` command
|
||||
|
||||
Surprisingly, `sleep` is an external command and not a `bash` built-in.
|
||||
|
||||
**CAVEAT:** Requires `bash` 4+
|
||||
## Convert a hex color to RGB
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
read_sleep() {
|
||||
# Usage: sleep 1
|
||||
# sleep 0.2
|
||||
read -rst "${1:-1}" -N 999
|
||||
hex_to_rgb() {
|
||||
# Usage: hex_to_rgb "#FFFFFF"
|
||||
# hex_to_rgb "000000"
|
||||
: "${1/\#}"
|
||||
((r=16#${_:0:2},g=16#${_:2:2},b=16#${_:4:2}))
|
||||
printf '%s\n' "$r $g $b"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
read_sleep 1
|
||||
read_sleep 0.1
|
||||
read_sleep 30
|
||||
$ hex_to_rgb "#FFFFFF"
|
||||
255 255 255
|
||||
```
|
||||
|
||||
## Check if a program is in the user's PATH
|
||||
|
||||
```shell
|
||||
# There are 3 ways to do this and either one can be used.
|
||||
type -p executable_name &>/dev/null
|
||||
hash executable_name &>/dev/null
|
||||
command -v executable_name &>/dev/null
|
||||
|
||||
# As a test.
|
||||
if type -p executable_name &>/dev/null; then
|
||||
# Program is in PATH.
|
||||
fi
|
||||
|
||||
# Inverse.
|
||||
if ! type -p executable_name &>/dev/null; then
|
||||
# Program is not in PATH.
|
||||
fi
|
||||
|
||||
# Example (Exit early if program is not installed).
|
||||
if ! type -p convert &>/dev/null; then
|
||||
printf '%s\n' "error: convert is not installed, exiting..."
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
## Get the current date using `strftime`
|
||||
|
||||
Bash’s `printf` has a built-in method of getting the date which can be used in place of the `date` command.
|
||||
|
||||
**CAVEAT:** Requires `bash` 4+
|
||||
## Convert an RGB color to hex
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
date() {
|
||||
# Usage: date "format"
|
||||
# See: 'man strftime' for format.
|
||||
printf "%($1)T\\n" "-1"
|
||||
rgb_to_hex() {
|
||||
# Usage: rgb_to_hex "r" "g" "b"
|
||||
printf '#%02x%02x%02x\n' "$1" "$2" "$3"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
# Using above function.
|
||||
$ date "%a %d %b - %l:%M %p"
|
||||
Fri 15 Jun - 10:00 AM
|
||||
|
||||
# Using printf directly.
|
||||
$ printf '%(%a %d %b - %l:%M %p)T\n' "-1"
|
||||
Fri 15 Jun - 10:00 AM
|
||||
|
||||
# Assigning a variable using printf.
|
||||
$ printf -v date '%(%a %d %b - %l:%M %p)T\n' '-1'
|
||||
$ printf '%s\n' "$date"
|
||||
Fri 15 Jun - 10:00 AM
|
||||
$ rgb_to_hex "255" "255" "255"
|
||||
#FFFFFF
|
||||
```
|
||||
|
||||
## Generate a UUID V4
|
||||
|
||||
**Example Function:**
|
||||
# CODE GOLF
|
||||
|
||||
```sh
|
||||
uuid() {
|
||||
# Usage: uuid
|
||||
C="89ab"
|
||||
## Shorter `for` loop syntax
|
||||
|
||||
for ((N=0;N<16;++N)); do
|
||||
B="$((RANDOM%256))"
|
||||
```shell
|
||||
# Tiny C Style.
|
||||
for((;i++<10;)){ echo "$i";}
|
||||
|
||||
case "$N" in
|
||||
6) printf '4%x' "$((B%16))" ;;
|
||||
8) printf '%c%x' "${C:$RANDOM%${#C}:1}" "$((B%16))" ;;
|
||||
# Undocumented method.
|
||||
for i in {1..10};{ echo "$i";}
|
||||
|
||||
3|5|7|9)
|
||||
printf '%02x-' "$B"
|
||||
;;
|
||||
# Expansion.
|
||||
for i in {1..10}; do echo "$i"; done
|
||||
|
||||
*)
|
||||
printf '%02x' "$B"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
# C Style.
|
||||
for((i=0;i<=10;i++)); do echo "$i"; done
|
||||
```
|
||||
|
||||
printf '\n'
|
||||
## Shorter infinite loops
|
||||
|
||||
```shell
|
||||
# Normal method
|
||||
while :; do echo hi; done
|
||||
|
||||
# Shorter
|
||||
for((;;)){ echo hi;}
|
||||
```
|
||||
|
||||
## Shorter function declaration
|
||||
|
||||
```shell
|
||||
# Normal method
|
||||
f(){ echo hi;}
|
||||
|
||||
# Using a subshell
|
||||
f()(echo hi)
|
||||
|
||||
# Using arithmetic
|
||||
# This can be used to assign integer values.
|
||||
# Example: f a=1
|
||||
# f a++
|
||||
f()(($1))
|
||||
|
||||
# Using tests, loops etc.
|
||||
# NOTE: ‘while’, ‘until’, ‘case’, ‘(())’, ‘[[]]’ can also be used.
|
||||
f()if true; then echo "$1"; fi
|
||||
f()for i in "$@"; do echo "$i"; done
|
||||
```
|
||||
|
||||
## Shorter `if` syntax
|
||||
|
||||
```shell
|
||||
# One line
|
||||
# Note: The 3rd statement may run when the 1st is true
|
||||
[[ "$var" == hello ]] && echo hi || echo bye
|
||||
[[ "$var" == hello ]] && { echo hi; echo there; } || echo bye
|
||||
|
||||
# Multi line (no else, single statement)
|
||||
# Note: The exit status may not be the same as with an if statement
|
||||
[[ "$var" == hello ]] && \
|
||||
echo hi
|
||||
|
||||
# Multi line (no else)
|
||||
[[ "$var" == hello ]] && {
|
||||
echo hi
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
## Simpler `case` statement to set variable
|
||||
|
||||
The `:` built-in can be used to avoid repeating `variable=` in a case statement. The `$_` variable stores the last argument of the last command. `:` always succeeds so it can be used to store the variable value.
|
||||
|
||||
```shell
|
||||
$ uuid
|
||||
d5b6c731-1310-4c24-9fe3-55d556d44374
|
||||
```
|
||||
# Modified snippet from Neofetch.
|
||||
case "$OSTYPE" in
|
||||
"darwin"*)
|
||||
: "MacOS"
|
||||
;;
|
||||
|
||||
## Progress bars
|
||||
"linux"*)
|
||||
: "Linux"
|
||||
;;
|
||||
|
||||
This is a simple way of drawing progress bars without needing a for loop
|
||||
in the function itself.
|
||||
*"bsd"* | "dragonfly" | "bitrig")
|
||||
: "BSD"
|
||||
;;
|
||||
|
||||
**Example Function:**
|
||||
"cygwin" | "msys" | "win32")
|
||||
: "Windows"
|
||||
;;
|
||||
|
||||
```sh
|
||||
bar() {
|
||||
# Usage: bar 1 10
|
||||
# ^----- Elapsed Percentage (0-100).
|
||||
# ^-- Total length in chars.
|
||||
((elapsed=$1*$2/100))
|
||||
*)
|
||||
printf '%s\n' "Unknown OS detected, aborting..." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Create the bar with spaces.
|
||||
printf -v prog "%${elapsed}s"
|
||||
printf -v total "%$(($2-elapsed))s"
|
||||
|
||||
printf '%s\r' "[${prog// /-}${total}]"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
for ((i=0;i<=100;i++)); do
|
||||
# Pure bash micro sleeps (for the example).
|
||||
(:;:) && (:;:) && (:;:) && (:;:) && (:;:)
|
||||
|
||||
# Print the bar.
|
||||
bar "$i" "10"
|
||||
done
|
||||
|
||||
printf '\n'
|
||||
```
|
||||
|
||||
## Get the list of functions in a script
|
||||
|
||||
```sh
|
||||
get_functions() {
|
||||
# Usage: get_functions
|
||||
IFS=$'\n' read -d "" -ra functions < <(declare -F)
|
||||
printf '%s\n' "${functions[@]//declare -f }"
|
||||
}
|
||||
```
|
||||
|
||||
## Bypass shell aliases
|
||||
|
||||
```shell
|
||||
# alias
|
||||
ls
|
||||
|
||||
# command
|
||||
# shellcheck disable=SC1001
|
||||
\ls
|
||||
```
|
||||
|
||||
## Bypass shell functions
|
||||
|
||||
```shell
|
||||
# function
|
||||
ls
|
||||
|
||||
# command
|
||||
command ls
|
||||
# Finally, set the variable.
|
||||
os="$_"
|
||||
```
|
||||
|
||||
<!-- CHAPTER END -->
|
||||
|
190
manuscript/chapter19.txt
Normal file
190
manuscript/chapter19.txt
Normal file
@ -0,0 +1,190 @@
|
||||
# OTHER
|
||||
|
||||
## Use `read` as an alternative to the `sleep` command
|
||||
|
||||
Surprisingly, `sleep` is an external command and not a `bash` built-in.
|
||||
|
||||
**CAVEAT:** Requires `bash` 4+
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
read_sleep() {
|
||||
# Usage: sleep 1
|
||||
# sleep 0.2
|
||||
read -rst "${1:-1}" -N 999
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
read_sleep 1
|
||||
read_sleep 0.1
|
||||
read_sleep 30
|
||||
```
|
||||
|
||||
## Check if a program is in the user's PATH
|
||||
|
||||
```shell
|
||||
# There are 3 ways to do this and either one can be used.
|
||||
type -p executable_name &>/dev/null
|
||||
hash executable_name &>/dev/null
|
||||
command -v executable_name &>/dev/null
|
||||
|
||||
# As a test.
|
||||
if type -p executable_name &>/dev/null; then
|
||||
# Program is in PATH.
|
||||
fi
|
||||
|
||||
# Inverse.
|
||||
if ! type -p executable_name &>/dev/null; then
|
||||
# Program is not in PATH.
|
||||
fi
|
||||
|
||||
# Example (Exit early if program is not installed).
|
||||
if ! type -p convert &>/dev/null; then
|
||||
printf '%s\n' "error: convert is not installed, exiting..."
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
## Get the current date using `strftime`
|
||||
|
||||
Bash’s `printf` has a built-in method of getting the date which can be used in place of the `date` command.
|
||||
|
||||
**CAVEAT:** Requires `bash` 4+
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
date() {
|
||||
# Usage: date "format"
|
||||
# See: 'man strftime' for format.
|
||||
printf "%($1)T\\n" "-1"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
# Using above function.
|
||||
$ date "%a %d %b - %l:%M %p"
|
||||
Fri 15 Jun - 10:00 AM
|
||||
|
||||
# Using printf directly.
|
||||
$ printf '%(%a %d %b - %l:%M %p)T\n' "-1"
|
||||
Fri 15 Jun - 10:00 AM
|
||||
|
||||
# Assigning a variable using printf.
|
||||
$ printf -v date '%(%a %d %b - %l:%M %p)T\n' '-1'
|
||||
$ printf '%s\n' "$date"
|
||||
Fri 15 Jun - 10:00 AM
|
||||
```
|
||||
|
||||
## Generate a UUID V4
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
uuid() {
|
||||
# Usage: uuid
|
||||
C="89ab"
|
||||
|
||||
for ((N=0;N<16;++N)); do
|
||||
B="$((RANDOM%256))"
|
||||
|
||||
case "$N" in
|
||||
6) printf '4%x' "$((B%16))" ;;
|
||||
8) printf '%c%x' "${C:$RANDOM%${#C}:1}" "$((B%16))" ;;
|
||||
|
||||
3|5|7|9)
|
||||
printf '%02x-' "$B"
|
||||
;;
|
||||
|
||||
*)
|
||||
printf '%02x' "$B"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
printf '\n'
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
$ uuid
|
||||
d5b6c731-1310-4c24-9fe3-55d556d44374
|
||||
```
|
||||
|
||||
## Progress bars
|
||||
|
||||
This is a simple way of drawing progress bars without needing a for loop
|
||||
in the function itself.
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
bar() {
|
||||
# Usage: bar 1 10
|
||||
# ^----- Elapsed Percentage (0-100).
|
||||
# ^-- Total length in chars.
|
||||
((elapsed=$1*$2/100))
|
||||
|
||||
# Create the bar with spaces.
|
||||
printf -v prog "%${elapsed}s"
|
||||
printf -v total "%$(($2-elapsed))s"
|
||||
|
||||
printf '%s\r' "[${prog// /-}${total}]"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
for ((i=0;i<=100;i++)); do
|
||||
# Pure bash micro sleeps (for the example).
|
||||
(:;:) && (:;:) && (:;:) && (:;:) && (:;:)
|
||||
|
||||
# Print the bar.
|
||||
bar "$i" "10"
|
||||
done
|
||||
|
||||
printf '\n'
|
||||
```
|
||||
|
||||
## Get the list of functions in a script
|
||||
|
||||
```sh
|
||||
get_functions() {
|
||||
# Usage: get_functions
|
||||
IFS=$'\n' read -d "" -ra functions < <(declare -F)
|
||||
printf '%s\n' "${functions[@]//declare -f }"
|
||||
}
|
||||
```
|
||||
|
||||
## Bypass shell aliases
|
||||
|
||||
```shell
|
||||
# alias
|
||||
ls
|
||||
|
||||
# command
|
||||
# shellcheck disable=SC1001
|
||||
\ls
|
||||
```
|
||||
|
||||
## Bypass shell functions
|
||||
|
||||
```shell
|
||||
# function
|
||||
ls
|
||||
|
||||
# command
|
||||
command ls
|
||||
```
|
||||
|
||||
<!-- CHAPTER END -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user