Open In App

Shell Script which Works Similar to the Unix Command HEAD TAIL

Prerequisites: Bash Scripting, Shell Function Library

HEAD and TAIL command print a specified number of lines of a file from the beginning and from the end respectively. If we don’t specify a number, the commands print the entire file. We will make a bash script display.sh which takes two to three arguments.



Creating Shell Script

The name of the script will be display.sh. Make it an executable file.

$ touch display.sh
$ chmod +x display.sh

Step 1: Handling Arguments and Errors



$ ./display.sh #invalid syntax (no arguments provided)

$ ./display.sh FILE #invalid syntax (options not specified)

$ ./display.sh -option NUM FILE #correct syntax

$ ./display.sh -option FILE #correct syntax

Open the file and add the following script :

#!/bin/bash

# if the number of args is less than 2, 
# then show the correct syntax to the user
if [ $# -lt 2 ] ; then
  echo "Invalid Syntax!"
  echo "The valid syntax is ./$(basename $0) [-h|t] NUM [FILE]"
  exit 1
fi

# storing the option (-h or -t)
option=$1

# if second argument is the file to be displayed
# then by default we will print all the lines
# otherwise we will store the number of lines
# to be printed
if [[ -f $2 ]]; then
  NUM=$(wc -l < "$2") #wc -l returns number of lines in a file
  FILE="$2" #store the file address
else
  NUM=$2
  FILE="$3"
fi

Error Handling. Prompts the user to use proper syntax

Step 2: Create Main Function

case $option in
  "-h") print_head $NUM $FILE
        exit;;
  "-t") print_tail $NUM $FILE
        exit;;
     *) echo "Invalid Option"
        exit 1
        exit;;
esac
exit 0

Step 3: Create print_head function

function print_head ()
{
  #print first NUM lines
  NUM=$1 ; FILE=$2 ; COUNTER=0 ; 
  while IFS= read -r line #will keep reading the file till the end
  do
    echo "$line"
    (( COUNTER++ ))
    if [ $COUNTER = $NUM ] ; then #if we have printed NUM lines; break
      break
    fi
  done < "$FILE"                        
}

Step 4: Create print_tail function

function print_tail ()
{
  #print last part of file
  NUM=$1 ; FILE="$2" ;
  total_lines=$(wc -l < "$FILE")

  #number of lines to be ignored
  if [ $NUM -ge $total_lines ] ; then
    IGNORE=0
  else
    IGNORE=$(( $total_lines - $NUM ))
  fi

  while IFS= read -r line
  do
    if [ $IGNORE -gt 0 ] ; then
      (( IGNORE-- ))
      continue
    fi
    echo "$line"
  done < "$FILE"
}

Step 5: Putting together everything

#!/bin/bash

function print_head ()
{
  #print first NUM lines
  NUM=$1 ; FILE=$2 ; COUNTER=0 ; 
  while IFS= read -r line #will keep reading the file till the end
  do
    echo "$line"
    (( COUNTER++ ))
    if [ $COUNTER = $NUM ] ; then #if we have printed NUM lines; break
      break
    fi
  done < "$FILE"                        
}

function print_tail ()
{
  #print last part of file
  NUM=$1 ; FILE="$2" ;
  total_lines=$(wc -l < "$FILE")

  #number of lines to be ignored
  if [ $NUM -ge $total_lines ] ; then
    IGNORE=0
  else
    IGNORE=$(( $total_lines - $NUM ))
  fi

  while IFS= read -r line
  do
    if [ $IGNORE -gt 0 ] ; then
      (( IGNORE-- ))
      continue
    fi
    echo "$line"
  done < "$FILE"
}

# if the number of args is less than 2,
# then show the correct syntax to the user
if [ $# -lt 2 ] ; then
  echo "Invalid Syntax!"
  echo "The valid syntax is ./$(basename $0) [-h|t] NUM [FILE]"
  exit 1
fi

#storing the option (-h or -t)
option=$1

#if second argument is the file to be displayed
#then by default we will print all the lines
#otherwise we will store the number of lines to be printed
if [[ -f $2 ]]; then
  NUM=$(wc -l < "$2") #wc -l returns number of lines in a file
  FILE="$2" #store the file address
else
  NUM=$2
  FILE="$3"
fi

case $option in
  "-h") print_head $NUM $FILE
        exit;;
  "-t") print_tail $NUM $FILE
        exit;;
     *) echo "Invalid Option!"
        exit 1
        exit;;
esac
exit 0

Run the Script

$ ./display.sh -h FILE

Printing the entire gfg.txt file

$ ./display.sh -h 4 FILE

Printing first 4 lines of gfg.txt

$ ./display.sh -t 6 file.txt
$ ./display.sh -t 1000 file.txt

Printing 6 lines from the last part of the file. If NUM exceeds total number of lines, it prints whole file

Handles invalid cases as well

Rejects invalid options, invalid arguments

Article Tags :