Get command line parameters using $#

if [[ $# -eq 2 ]]; then
    echo ""
fi

for loop

for f in *.tar*;  do 
    
done

Format output using printf

printf "\n %-10s %8s %10s %11s\n" "ITEM NAME" "ITEM ID" "COLOR" "PRICE"
format=" %-10s %08d %10s %11.2f\n"
printf "$format" \
Triangle 13  red 20 \
Oval 204449 "dark blue" 65.656 \
Square 3145 orange .7

Check if file or directory exists

if [ -f ~/.bashrc ]; then
    echo "file exists";
fi
if [ -d ~/.ssh ]; then
    echo "Directory exists";
fi

Know which shell you are working on

echo $0
echo $SHELL

Formatted output using printf

format="%28s %-7s %40s %15s"
printf "$format" "file transfered to server - " "success" " - $FILE_TO_TRANSFER" "- $server:/tmp" >> output.log

Creating array from the string

str="autoconf has no dependents. automake has no dependents."
IFS=.
ary=($str_list)
for key in "${!ary[@]}"; do 
    echo "$key ${ary[$key]}";
done
IFS=$'\n'
serverList=$( cut -d',' -f1 server_list.txt | uniq -i)
read -rd '' -a servers <<< "$serverList"
for server in "${!servers[@]}"
do
    result=$(ssh -t $server 'uptime')
    echo "$server uptime is $result"
done

Loop through an array

launchctlFind () {
    LaunchctlPATHS=( \
        ~/Library/LaunchAgents \
        /Library/LaunchAgents \
        /Library/LaunchDaemons \
        /System/Library/LaunchAgents \
        /System/Library/LaunchDaemons \
    )

    for curPATH in "${LaunchctlPATHS[@]}"
    do
        grep -r "$curPATH" -e "$1"
    done
    return 0;
}
# another example
declare -a arr_str=("STR1"
                    "STR2"
                    "STR3")
for str in "${arr_str[@]}"; do
    echo "$str";
done

Round float values

# Round Float value to floor 99.8 -> 100
CPU_USAGE=99.8
CPU_USAGE_INT=$( printf "%.0f" $CPU_USAGE )
# Round Float value to ceil 99.8 -> 99
CPU_USAGE=99.8
CPU_USAGE_INT=`echo $CPU_USAGE | awk '{print int($0)}'`

Execute command using character `

CPU_USAGE_INT=`echo $CPU_USAGE | awk '{print int($0)}'`

Get file name and extension

fileExtension="${fullFileName##*.}"
 fileName="${fullFileName%.*}"

Loop through tar files and create a folder with the name

for f in *.tar*;  do 
    fileName=$(basename $f); 
    dirName=${fileName:0:${#fileName} - 7}; 
    mkdir $dirName; 
    tar -xvzf $f -c $dirName; 
done

Loop through the content of a file

while read LINE
do
    echo "$LINE"
done < file.txt
IFS=$'\n'
set -f     # Disable globbing
for LINE in $(cat < "$1"); do
      echo "$LINE"
done

Check if grep returns some result or not

if ! grep -q ".bashrc" ~/.bash_profile ; then
    echo "adding .bashrc to .bash_profile"
    echo ". ~/.bashrc" >> ~/.bash_profile;
    source ~/.bash_profile;
else
    echo "** .bashrc already exists in .bash_profile"
fi
TEST=$(ps -ef | grep crond)
 
if [ "$TEST" != "" ]
then
    echo "crond is already running"
else
    echo "starting crond"
    /usr/bin/crond
fi

Trim String

function trim()
{
    str="$1"
    result=$(echo $str | sed 's/^ *//g')
    result=$(echo $result | sed 's/ *$//g')
    echo $result
}
find . -type d -print0 | sort -z | while read -d '' -r dir; do
    files=("$dir"/*);
    printf "%5d files in directory %s\n" "${#files[@]}" "$dir";
done

Display file names with spaces

find . -type f -name "*.csv" -print0 | while IFS= read -r -d '' file; do
    echo "file = $file"
done

OIFS="$IFS"
IFS=$'\n'
for file in `find . -type f -name "*.csv"`  
do
     echo "file = $file"
done
IFS="$OIFS"

Find Songs With Lyrics

find . -type f -iname "*.mp3" -print0 | while IFS= read -r -d '' file; do 
    lyrics=$(exiftool -TAG "-Lyrics" "$file"); 
    if [[ ${#lyrics} -gt 300 ]]; then 
         echo "$file---->${#lyrics}----> YES"; 
    fi  
done

Use awk to count sum of files in folders

for d in $(find . -type d ); do 
    if [ "$(ls $d)" ]; then 
        echo "$d > $(ls -l $d | wc -l)"; 
    fi 
done | awk -F'>' '{ gsub(/ /,"",$2); sum += $2; if($2>100) printf "%-120s -> %-4s -> %-6s\n", $1, $2, sum}'

Find empty directories

for d in $(find . -type d); 
do
         if [ -z "$(find $d -type f)" ]; then 
                    echo "$d is empty"; 
         fi
done

Increment counter inside while loop

Note that the counter here is still zero.

counter=0
find ~/scripts/python/2_photos/ -type f -iname "$1" | while read -r file; do
      counter=$((count+1))
done
echo "counter - $counter"

This is the correct approach for the counter to hold its incremented value after the loop.

counter=0
while read -r file; do
      counter=$((count+1))
done < <(find ~/scripts/python/2_photos/ -type f -iname "$1")
echo "counter - $counter"
function printHelp()
{
   cat <<EOT
   
   ---Description---
   This is about using cat wisely
 
   --Usage--
   test <params>
   
   EOT
}
cat << EOF > /drive/file.txt
The content you want to write here
which could be a multi line
EOF
# In order to disable interpreting variables use single quotes
cat >> 'EOF' > /drives/file.txt
Disable vairable interpretation $VAR
EOF
# Use <<- (followed by a dash) to disable leading tabs in a script
# This is mainly useful when you use indentation in the script
# Below example, cat is started with a tab. So use <<-
 
while true; do
   cat <<- EOF > /drives/file.txt
   Enter all the files you want
   here
   EOF
done

Get File path / basename

FILE=/User/Documents/testing.tar.gz
FILE_PATH=${FILE%/*} 
FILE_BASE=${FILE##*/}
FILE_PREFIX=${FILE_BASE%.*} 
FILE_EXT=${FILE_BASE##*.}

Get first few characters of a string

FILE_NAME=" file_name_with_first_space.mp3"
FIRST_CHAR="${FILE_NAME:0:1}"
if [[ $FIRST_CHAR == " " ]]; then      
      echo "FILE first char is space"; 
fi

Removing First Empty Space In File Names

while read -r file; do 
  FILE_NAME=${file##*/}; 
  FIRST_CHAR="${FILE_NAME:0:1}"; 
  if [[ $FIRST_CHAR == " " ]]; then 
    # trim file name
    result="$(echo $FILE_NAME | sed 's/^ *//g')";  
    result=$(echo $result | sed 's/ *$//g'); 
     echo "Renaming FILE >$FILE_NAME< TO >$result<"; 
    mv "$FILE_NAME" "$result";  fi 
done < <(find . -type f)

Extract content between two specific lines

Extract content between two specific lines and give it as input to another command

BEGIN_LINE="-----BEGIN CERTIFICATE-----"
END_LINE="-----BEGIN CERTIFICATE-----"
EXTRACTED_CONTENT=""
READ="false"
PRINT="false"
READ_BEGIN_END="true"
while read LINE; do	
	if [ "$END_LINE" = "$LINE" ]; then
		READ="false"
		PRINT="true"
	fi
	
	if [ "$READ" == "true" ]; then
		EXTRACTED_CONTENT="$EXTRACTED_CONTENT$LINE\n"
	fi 
	 
	if [ "$PRINT" == "true" ]; then
		if [ "$READ_BEGIN_END" == "true" ]; then
			BEGIN_CONTENT="$BEGIN_LINE\n"
			END_CONTENT="$BEGIN_LINE\n"
			EXTRACTED_CONTENT="$BEGIN_CONTENT$EXTRACTED_CONTENT$END_CONTENT"
		fi
		printf %*s $COLUMNS | tr ' ' '-'
		printf -- "$EXTRACTED_CONTENT" | openssl x509 -noout -text
		printf -- "$EXTRACTED_CONTENT" | openssl x509 -noout -sha1 -fingerprint
		EXTRACTED_CONTENT=""
		PRINT="false"
	fi 
	
	if [ "$BEGIN_LINE" = "$LINE" ]; then 
		READ="true"
	fi 
 
done < /tmp/all_public_certs.pem

If String contains

str=testing
substr=test
if [ "${str/$substr}" = "$str" ] ; then
  echo "${substr} is not in ${str}"
else
  echo "${substr} was found in ${str}"
fi
 
string='testing'
if [[ $string == *"test"* ]]; then
  echo "It's there!"
fi

loop through grep result

grep xyz abc.txt | while read -r line ; do
    echo "Processing $line"
    # your code goes here
done

The -r option to read prevents backslash interpretation (usually used as a backslash newline pair, to continue over multiple lines or to escape the delimiters). Without this option, any unescaped backslashes in the input will be discarded. You should almost always use the -r option with read.

In the scenario above IFS= prevents trimming of leading and trailing whitespace. Remove it if you want this effect.

  • http://mywiki.wooledge.org/BashFAQ/001
while read -r line ; do
    echo "Processing $line"
    # your code goes here
done < <(grep xyz abc.txt)