Conditional Expression
Note: EXPR && echo true - on returningtrue expression is true, otherwise false.
String
  
    
      | Expression | 
      Description | 
    
  
  
    
      [ "$VAR" ] | 
      String not empty | 
    
    
      [ -z "$VAR" ] or [ ! "$VAR" ] | 
      String is empty | 
    
    
      [ "$VAR1" = "$VAR2" ] | 
      Equal string - case-sensitive | 
    
    
      [ "${VAR1,,}" = "${VAR2,,}" ] | 
      Equal string - case-insensitive | 
    
    
      [ "$VAR1" != "$VAR2" ] | 
      Not equal string | 
    
    
      [[ "$VAR" =~ "REGEX" ]] | 
      String matches REGEX | 
    
  
File
  
    
      | Expression | 
      Description | 
    
  
  
    
      [ -e "$VAR" ] | 
      File/directory exists | 
    
    
      [ -d "$VAR" ] | 
      Directory exists | 
    
    
      [ -f "$VAR" ] | 
      Regular file exists | 
    
    
      [ -s "$VAR" ] | 
      Regular file exists and not empty | 
    
    
      [ -r "$VAR" ] | 
      Regular file exists with read permission | 
    
    
      [ -w "$VAR" ] | 
      Regular file exists with write permission | 
    
    
      [ -x "$VAR" ] | 
      Regular file exists with exec permission | 
    
  
Elvis Operator (Ternary)
[REF]
  
    
      | Expression | 
      Description | 
    
  
  
    
      $(( $ORG == 1 ? ${VAL1} : ${VAL2} )) | 
      inline expression & variable assignment | 
    
    
      $( [ $ORG == "1" ] && echo ${VAL1} || echo ${VAL2} ) | 
      inline expression & variable assignment | 
    
    
      [ $ORG == "1" ] && VAR="1" || VAR="2" | 
      only variable assignment | 
    
    
      ${VAR:-DEFAULT} | 
      if VAR is unset or null, DEFAULT is returned | 
    
    
      ${VAR:=DEFAULT} | 
      if VAR is unset or null, DEFAULT is returned and set to VAR itself | 
    
  
String Operation
Shell Parameter Expansion
  
    
      | Expression | 
      Description | 
    
  
  
    
      ${VAR:-DEFAULT} | 
      If VAR is unset or null, DEFAULT is returned | 
    
    
      ${VAR:=DEFAULT} | 
      If VAR is unset or null, DEFAULT is returned and set to VAR itself | 
    
    
      ${VAR:IDX[:LEN]} | 
      VAR.substr(IDX [,LEN]) | 
    
    
      ${VAR,,} | 
      VAR.toLowercase | 
    
    
      ${VAR^^} | 
      VAR.toUppercase | 
    
    
      ${VAR/PAT/STR} | 
      VAR.replaceFirst(PAT, STR) | 
    
    
      ${VAR//PAT/STR} | 
      VAR.replaceAll(PAT, STR) | 
    
    
      ${!VAR} | 
      consider it as ${${VAR}} | 
    
  
Split by Delimiter
  - Set 
IFS variable to delimiter 
  read -ra ARRAY <<< STRING
    
      -r - Backslash does not act as an escape character 
      -a ARRAY - The words, separated by IFS, are assigned to the sequential index of array ARRAY beginning at zero. 
    
   
  - Access
    
      - By Index - 
${ARRAY[0]}, and so on 
      - Iteration - 
for i in "${ARRAY[@]}"; do ... 
    
   
1
2
3
4
5
6
7
8
9
10
  | if [[ "${SCHEMA}" =~ "|" ]]; then
    IFS="|"
    read -ra PARTS <<< "${SCHEMA}"
    SCHEMA_PARAM="schemas=${PARTS[0]} remap_schema=${PARTS[1]}"
else
    SCHEMA_PARAM="schemas=${SCHEMA}"
    if [[ "${SCHEMA}" =~ ":" ]]; then
        SCHEMA_PARAM="remap_schema=${SCHEMA}"
    fi
fi
 | 
 
Loop
for
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  | ## Iterate over CMD output using $() 
for i in $(seq 1 1 10); do
  echo "i = $i"
done
## Iterate on words: 'Hi!', 'Visit', 'https://devocative.org', and '!'
STR="Hi! Visit https://devocative.org !"
for w in ${STR}; do
  echo "w = $w"
done
## Iterate over lines
LINES=$(cat << 'EOF'   # EOF must be enclosed in single quote
export LS_OPTIONS='--color=auto'
eval "`dircolors`"
alias ll='ls $LS_OPTIONS -l'
EOF
) # closed parenthesis must be in the next line
IFS=$'\n'
for l in ${LINES}; do
  echo "LINE = $l"
done
## Iterate over files
for f in /usr/lib*; do
  echo "f = $f"
done
## Iterate over input parameters
for var in "${@}"; do
  EXP="${var//[\/:]/_}.tar"
  echo "Exporting: ${var} to ${EXP}"
  docker save ${var} -o ${EXP}
done
 | 
 
Function
  - Good [Ref]
 
  - Note: 
function keyword not valid for POSIX sh. For bash is also optional. 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  | # check required param
function rq() {
    VAR="$1"
    MSG="$2"
    
    if [ -z "$VAR" ]; then
        echo "ERROR: ${MSG}"
        exit 1
    fi
}
function func1() {
    rq "$1" "func1 *[PARAM1] *PARAM2 PARAM3"
    rq "$2" "func1 *PARAM1 *[PARAM2] PARAM3"
    
    PARAM1="$1"
    PARAM2="$2"
    PARAM3="$3"
    
    # ...
}
func1 "V1" "V2" 
#
# function with return value
#
function add() {
    rq "$1" "add *[PARAM1] *PARAM2"
    rq "$2" "add *PARAM1 *[PARAM2]"
    PARAM1="$1"
    PARAM2="$2"
    echo $((PARAM1 + PARAM2))  # No need to use $ for variables inside '(())'! 
}
echo "3 + 6 = $(add "3" "6")"
 | 
 
Samples
Inline Code Block in Background (*)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  | {
  for i in $(seq 1 1 5); do
    echo "block = $i"
    sleep 1
  done
} &
for i in $(seq 1 1 5); do
  echo "main = $i"
  sleep 2
done
##
## example from following REF! Note using 'wait' command!
{
    echo "sleeping for 5 seconds"
    sleep 5
    echo "woke up"
} &
echo "waiting"
wait
echo "proceed"
 | 
 
[REF]
Assert Env Var
  - For 
bash
    1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  | E2=b
ENV_VARS="
E1
E2
E3
"
  
function assertEnvVars() {
    VARS="$1"
    for VAR in ${VARS}; do              # ITERATE OVER WORDS IN STRING
      echo "${VAR}"
      if [[ ! "${!VAR}" ]]; then        # USING ${!} STRING EXPANSION
        echo "Var Not Defined: ${VAR}"
      fi
    done
}
  
assertEnvVars "${ENV_VARS}"  # DOUBLE-QUOTE REQUIRED
 | 
      
   
  - For POSIX 
sh
    1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  | E2=b
  
ENV_VARS="
E1
E2
E3
"
  
assertEnvVars() {                    # No 'function' Keyword!
  VARS="$1"
  for VAR in ${VARS}; do
    echo "${VAR}"
    eval VAR_VAL="\$${VAR}"          # USE 'eval' instead of '${!}'
    if [ ! "${VAR_VAL}" ]; then      # No '[[]]' Support!
      echo "Var Not Defined: ${VAR}"
    fi
  done
}
  
assertEnvVars "${ENV_VARS}"  # DOUBLE-QUOTE REQUIRED
 | 
      
   
Command with Proxy
A simple script to set http_proxy env variable in current shell and then executes passed parameters as commands.
Note: replace HOST and PORT with your configuration.
1
2
3
4
5
  | #! /bin/bash
export http_proxy="http://HOST:PORT"
eval "$@"
  | 
 
Dynamic Music Player
  - In XFCE keyboard layout, for example set 
ctrl + alt + p to call following script with pop (play or pause) parameter. 
  - The player can be 
parole or smplayer or anything you want. 
  - Based on priority and running processes, the script decides to send action to selected player.
 
Upload to a Docker Registry
My tmux
Usage: mytmux.sh CMD...
  - For a multi-word command, surround it with single or double quote
 
  - Example: 
mytmux.sh 'tail -f file1' 'tail -f file2' 
Pars Parametric Text File
[REF]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  | # Create a simple text file
#  > means create, >> means create/append
#  it should be double <<
#  EOF means parametric string, while 'EOF' means pure string
#  CR should be after first EOF and before second one
cat > myfile.txt << 'EOF'
Hello "${MSG}"!
'${MSG}' has "$(printf '${MSG}' | wc -m)" chars :-)
EOF
MSG="World"
printf "*** Using 'eval & cat':\n"
eval "cat <<EOF
$(<myfile.txt)
EOF" | cat
printf "\n*** Using 'eval & echo':\n"
eval "echo \"$(<myfile.txt)\"" | cat
printf "\n*** Using 'envsubst':\n"
export MSG
envsubst < myfile.txt | cat
rm -f myfile.txt
 | 
 
Note: | cat in all above is just for simulation of another action on the processed file, so it is rudimentary.
Output is
1
2
3
4
5
6
7
8
9
10
11
  | *** Using 'eval & cat':
Hello "World"!
'World' has "6" chars :-)
*** Using 'eval & echo':
Hello World!
'World' has 6 chars :-)
*** Using 'envsubst':
Hello "World"!
'World' has "$(printf 'World' | wc -m)" chars :-)
  | 
 
Iterate over JSON Array
[REF]
1
2
3
4
5
6
7
8
9
  | sample='[{"name":"foo"},{"name":"bar"}]'
for obj in $(echo "${sample}" | jq -r '.[] | @base64'); do
  _jq() {
    echo ${obj} | base64 --decode | jq -r ${1}
  }
  
  echo $(_jq '.name')
done
 | 
 
LVM Partition Smart Expand
Setting the partition name, following script find a block device and extend the associated logical volume.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  | P_EXTEND="/var"
if [ "${P_EXTEND}" ]; then
  echo "Extending Partition: ${P_EXTEND}"
  MAP="$(df --output=source ${P_EXTEND}  | sed 1d)"
  VG="$(lvs -o vg_name,lv_path,lv_dmpath --noheadings | grep "${MAP}" | awk '{print $1}')"
  LV="$(lvs -o vg_name,lv_path,lv_dmpath --noheadings | grep "${MAP}" | awk '{print $2}')"
  echo "VG = ${VG}, LV = ${LV}, MAP = ${MAP}"
  B_DEV="$(pvs -a --noheadings | grep -v ${VG} | awk '{print $1}')"
  echo "BLOCK_DEV = ${B_DEV}"
  if [ "${B_DEV}" ]; then
    vgextend ${VG} ${B_DEV}
    lvextend -r -l +100%FREE ${LV}
  fi
fi
 | 
 
Git/Maven Create Next Snapshot
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  | #!/bin/bash
if [ ! "$1" ]; then
  echo "Pass next version: $0 VERSION"
  exit 1
fi
if [[ "$1" =~ -SNAPSHOT$ ]]; then
  NEW_VERSION="$1"
else
  NEW_VERSION="$1-SNAPSHOT"
fi
echo "Next snapshot version: $NEW_VERSION"
mvn versions:set -DnewVersion="${NEW_VERSION}" -DgenerateBackupPoms=false
git status --porcelain | awk 'match($2, "pom.xml"){print $2}' | xargs git add
git commit -m "Create Next Snapshot: ${NEW_VERSION}"
 |