#!/bin/bash # copyright 2007 Gilbert Ashley # BashTrix head is an implementation of the 'head' command # written in pure shell. Most head options are supported. VERSION=0.1 # show program usage show_usage() { echo echo "Usage: ${0##/*} [OPTION]... [FILE]..." echo "${0##/} -[m|w|l|L] FILE" echo " or: (cat|echo) | ${0##/*} [OPTION]... " echo "Print the first 10 lines of each FILE to standard output." echo "With more than one FILE, precede each with a header giving the file name." echo "With no FILE, read standard input." #echo " -m, --chars print the character counts" echo " -n[-]N, --lines=[-]N print the first N lines instead of the first 10." echo " With the leading '-', print all but the last" echo " N lines of each file (except when reading stdin)." echo " -q, --quiet, --silent never print headers giving file names" echo " -v, --verbose always print headers giving file names" echo " --help display this help and exit" echo " --version output version information and exit" exit } show_version() { echo ${0##/*}" (BashTrix) $VERSION" echo "Copyright 2007 Gilbert Ashley " echo "This is free software written in pure shell." exit } # show usage if '-h' or '--help' is the first argument or no argument is given case $1 in "-h"|"--help") show_usage ;; "--version") show_version ;; esac for WORD in "$@" ; do case $WORD in -*) true ; case $WORD in -n) REQUESTED_LINES=$2 ; shift 2 ;; -n-*) REQUESTED_LINES=${WORD:2} ; shift ;; -n*) REQUESTED_LINES=${WORD:2} ; shift ;; --lines=*) REQUESTED_LINES=${WORD:8} ; shift ;; -q|--quiet|--silent) SHOW_HEADERS=0 ; shift ;; -v|--verbose) SHOW_HEADERS=1 ; shift ;; --help) show_usage ;; --version) show_version ;; -) READ_STDIN=1 ; shift ;; *) echo "Unrecognized argument" ; show_usage ;; esac ;; esac done if [[ $# -gt 0 ]] ; then while [[ $# -gt 0 ]] ; do FILE_NAME="$1" if [ ! -r "$1" ] ; then echo "Cannot find file $1" 1>&2 exit 1 else FILE_LINE_COUNT=0 LINE= IFS= # count the total lines in the file while read LINE ; do # add the curent line to the line counter (( FILE_LINE_COUNT++ )) done <"$1" # figure out which lines to print START=1 if [[ ${REQUESTED_LINES} = "" ]] ; then FINISH=10 elif [[ ${REQUESTED_LINES:0:1} = "-" ]] ; then FINISH=$(( ${FILE_LINE_COUNT} - ${REQUESTED_LINES:1} )) else FINISH=$(( ${REQUESTED_LINES} )) fi # write the header output if requested if [[ $SHOW_HEADERS ]] ; then echo "==> $FILE_NAME <==" fi # reset to the start and print the requested lines FILE_LINE_COUNT=0 while read LINE ; do # add the curent line to the line counter (( FILE_LINE_COUNT++ )) if [[ $FILE_LINE_COUNT -ge $START ]] \ && [[ $FILE_LINE_COUNT -le $FINISH ]] ; then # output this line echo $LINE fi # go to next LINE done <"$1" fi # go to next FILE in $@ shift done else # piped input is presumed to be separated into lines already FILE_NAME="STDIN" # figure out which lines to print START=1 if [[ ${REQUESTED_LINES} = "" ]] ; then FINISH=10 #elif [[ ${REQUESTED_LINES:0:1} = "-" ]] ; then # FINISH=$(( ${FILE_LINE_COUNT} - ${REQUESTED_LINES:1} )) elif [[ ${REQUESTED_LINES:0:1} = "-" ]] ; then echo "This syntax not supported when reading stdin" exit 1 else FINISH=$(( ${REQUESTED_LINES} )) fi # write the header output if requested if [[ $SHOW_HEADERS ]] ; then echo "==> $FILE_NAME <==" fi # output the requested lines in the file FILE_LINE_COUNT=0 LINE= IFS= while read LINE ; do # add the curent line to the line counter (( FILE_LINE_COUNT++ )) if [[ $FILE_LINE_COUNT -ge $START ]] \ && [[ $FILE_LINE_COUNT -le $FINISH ]] ; then # output this line echo $LINE fi done fi