Bash Basics https://devhints.io/bash **Note** - for executing commands if uses single quotes then it will pass literal text , double quotes allows commands and variables to be execured   - for loop ```bash for arg in "$@"; do echo "$arg" done for (( i=0;i<$filesCount;i++)); do singleFile="${filesArray[$i]}" #here I replace ALL the spaces in the file's name, by underscores. trimmed=${singleFile// /\_} mv "${singleFile}" "${trimmed}" echo "renamed ${singleFile} as ${trimmed} !" done ``` - if elif else set of if else statements are terminated with fi ```bash # String if [[ -z "$string" ]]; then echo "String is empty" elif [[ -n "$string" ]]; then echo "String is not empty" else echo "This never happens" fi ``` - Logical operators ```bash # Logical AND and OR if [[ $varA == 1 && ($varB == "t1" || $varC == "t2") ]]; then # NOT if ! [[ $var == 2 || $var == 30 || $var == 50 ]] ; then do something fi if [[ ! ($var == 2 || $var == 30 || $var == 50) ]] ; then do something fi ``` - Functions ```bash myfunc() { echo "hello $1" } # Same as above (alternate syntax) function myfunc { echo "hello $1" } myfunc "John" # Returning values myfunc() { local myresult='some value' echo "$myresult" } result=$(myfunc) ``` - Geting filename and extemsion ```bash # First, get file name without the path: filename=$(basename -- "$fullfile") # or filename="${FILEPATH##*/}" extension_only="${filename##*.}" filename_with_noext="${filename%.*}" ``` - array ```bash # Declaring an array arr=() arr1=("hey" "there" "how") arr2=("er" "yu") declare -a arr3=() # Declare associative array to be able to have keys rather than index declare -A asscoArr # array elements is "${arr1[@]}" for ele in "${arr1[@]}";do echo $ele done # Output hey there how # array index/keys is "${!arr1[@]}" for i in "${!arr1[@]}";do echo $i done # Accessing elements through index "${arr1[2]}" # getting length of array ${#arr1[@]} ``` - shift To shift arguments to left so that first argument is lost - C like switch case in bash ```bash #!/bin/bash # Loop through all the arguments for arg in "$@"; do case $arg in -a|--optionA) echo "Option A detected!" # handle option A ;; -b|--optionB) echo "Option B detected!" # handle option B ;; *) # Handle positional arguments or invalid flags ;; esac done ``` - pasing variable arguments ```bash # Define your arguments in an array passargs=(-x '*/node_modules/*') # Use the array with the command zip -r archive.zip . "${passargs[@]}" # following method wont work passargs="'-x */node_modules/*'" zip -r $ARCHIVE_NAME $FILES_TO_ARCHIVE $passargs ``` - convert string which r separted by spaces to array using declare will resolve some bugs related to delimiters ```bash # arrow looks like following arr1=('hey' 'there') # if str="hey there" declare -a arr=($str) # now # arr is ('hey' 'there') ``` - extract parent directory ```bash // Output : /home/username echo "$PWD" // Output : /home echo "${dirname $PWD}" ``` ### Examples - Find non common elements from 2 array ```bash distinctive_files(){ # dir1=$1 # dir2=$2 # arr1=( $( ls $dir1 ) ) # arr2=( $( ls $dir2 ) ) declare -a arr1=("er" "rt") declare -a arr2=("er" "rt" "ty") # echo "arr1: ${arr1[@]}" # echo "arr2: ${arr2[@]}" declare -A all_Elements common_Files=() distinct_Files=() for elem in "${arr1[@]}";do # echo "elem arr1: $elem" ((all_Elements[$elem]++)) # echo "arr1 all_Elements: ${all_Elements[$elem]}" done for elem in "${arr2[@]}";do # echo "elem arr2: $elem" ((all_Elements[$elem]++)) # echo "arr2 all_Elements: ${all_Elements[$elem]}" done # echo "Non common elements:" for key in "${!all_Elements[@]}" ; do if [ ${all_Elements[$key]} -eq 1 ]; then distinct_Files+=($key) fi # echo "key: $key" done echo "${distinct_Files[@]}" # Calling function disti=$(distinctive_files) ``` - Pass 2 arrays as arguments in bash ```bash # by passing number of elements of each array myFunc(){ local n1=$1 local n2=$2 shift 2 local arr=("$@") arr1=() arr2=() i=0 for ele in "${arr[@]}"; do echo "ele: $ele" if [[ i -ge $n1 ]]; then arr2+=($ele) else arr1+=($ele) fi ((i++)) done echo "arr1 ${arr1[@]}" echo "arr2 ${arr2[@]}" } declare -a arr1=("er" "rt") declare -a arr2=("er" "rt" "ty") (added_zipped_files ${#arr1[@]} ${#arr2[@]} ${arr1[@]} ${arr2[@]}) # by passing reference(from bash 4.3 released in year 2016) demo_multiple_arrays() { local -n _array_one=$1 local -n _array_two=$2 printf '1: %q\n' "${_array_one[@]}" printf '2: %q\n' "${_array_two[@]}" } array_one=( "one argument" "another argument" ) array_two=( "array two part one" "array two part two" ) demo_multiple_arrays array_one array_two ``` - Append certain character ```bash #!/bin/bash # Check if a file name is provided as an argument if [ $# -ne 1 ]; then echo "Usage: $0 " exit 1 fi # Check if the file exists if [ ! -f "$1" ]; then echo "File '$1' not found." exit 1 fi # Append semicolon to each line in the file while IFS= read -r line; do echo "$line;" done < "$1" > "$1.tmp" # Replace the original file with the modified one mv "$1.tmp" "$1" echo "Semicolons appended to each line in '$1'." ``` - to display ram of top processes based on ram ```sh #!/bin/zsh echo "Command PSS (MB)" echo "=================================================" smem -c "command pss" | awk '{ cmd=$1; pss=$2; uss=$3; rss=$4; pssTotal[cmd]+=pss; ussTotal[cmd]+=uss; rssTotal[cmd]+=rss; } END { for (cmd in pssTotal) { # Convert from KB to MB pssMB = pssTotal[cmd] / 1024; printf "%-35s %10.2f MB\n", cmd, pssMB; } }' | sort -k 2 -nr | head -n 10 ``` - random string generation random 16 character alphanumeric string `tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 16; echo ''` pure bash ```sh # Define allowed character set chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' length=16 result='' for ((i=0; i