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.
- –h or -t option to specify whether to print from head or tail
- NUM to specify the number of lines to be printed
- If NUM is not specified, the script shall print the whole file.
- If NUM exceeds the total number of lines in a file, the script shall print the whole file as usual.
- FILE address
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
- We will store the arguments in variable
- It works even if the file name contains spaces. Make sure to add double quotes. For example : ./display.sh -h 10 “file name”
- wc -l command returns the total number of lines in a file.
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
- If the option is -h, the print_head function will be called.
- If the option is -t, the print_tail function will be called.
- If the option is invalid, the script will exit 1
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"
}
- read command trims white spaces. To avoid that, include IFS= in your script.
- -r option enables us to print escape sequences in the file as well.
- COUNTER variable keeps the count of lines that have been printed.
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"
}
- We start reading the file line by line from the beginning.
- IGNORE variable will keep a track of how many lines at the beginning we have to ignore, and thus not print them.
- The rest of the lines will be printed once IGNORE becomes equal to 0.
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
Last Updated :
09 Aug, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...