joplin-notes/joplin notion extension/linux/Bash Basics.md
2026-11-04 00:33:23 +05:30

6.7 KiB

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

      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

      # 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

    # 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

      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

    # First, get file name without the path:
    
     filename=$(basename -- "$fullfile")
     # or
     filename="${FILEPATH##*/}"
     extension_only="${filename##*.}"
     filename_with_noext="${filename%.*}"
    
    
  • array

    # 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

    #!/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

    # 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

    # arrow looks like following
    arr1=('hey' 'there')
    # if
    str="hey there"
    declare -a arr=($str)
    # now 
    # arr is ('hey' 'there')
    
  • extract parent directory

    // Output : /home/username
    echo "$PWD"
    
    // Output : /home
    echo "${dirname $PWD}"
    
    
    

Examples

  • Find non common elements from 2 array
    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
    # 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
    #!/bin/bash
    
      # Check if a file name is provided as an argument
      if [ $# -ne 1 ]; then
      	echo "Usage: $0 <filename>"
      	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
    #!/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
# Define allowed character set
chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
length=16
result=''

for ((i=0; i<length; i++)); do
  result+="${chars:RANDOM%${#chars}:1}"
done

echo "$result"

 

for have single quotes in literal in bash

ffmpeg -i 'The Witcher 3 In the Eternal Fire'\''s Shadow p1.mp4' -o ...