#!/bin/bash # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # ocelot -- The cute alternative to cat (with headers!) # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # Author: binaryDiv # # Version: 1.1.0 # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # Strict mode set -euo pipefail IFS=$'\n\t' BASENAME=$(basename $0) # Global options STYLE=big PREFIXCHAR='#' LINECHAR='~' # Helper functions # ---------------- # Prints help text function usage { cat << END_OF_HELPTEXT Usage: $BASENAME [OPTION] FILE... Prints all FILEs with their filename as a header. Like cat but more cute. If FILE is '-', it reads from standard input. General options: -h print this help message Style options: -b show big headers (with lines above and under filename; default) -s show single lined headers (only prefix and filename) -n no style, just print filename and content -p PREFIX use PREFIX in front of the header lines (default: '#') -l LINECHAR use LINECHAR as character for lines in big headers (default: '~') END_OF_HELPTEXT } # Print a single file with header function print_file_with_header { file=$1 print_header $file print_file $file echo } # Prints a header function print_header { text=$1 if [[ $text == '-' ]]; then text='STDIN' fi case $STYLE in big) header_style_big "$text" ;; singleline) header_style_singleline "$text" ;; none | *) header_style_none "$text" ;; esac } # Print error message function print_error { text=$1 echo "${PREFIX}[$text]" } # Prints content of file function print_file { file=$1 if [[ -f $file || -p $file || $file == '-' ]]; then cat $file elif [[ -d $file ]]; then print_error "File is a directory" else print_error "File does not exist" fi } # Define header styles # -------------------- function header_style_none { text=$1 echo $text } function header_style_singleline { text=$1 echo "${PREFIX}${text}" } function header_style_big { text=$1 length=${#text} echo -n "${PREFIX}"; characterline $LINECHAR $length echo "${PREFIX}${text}" echo -n "${PREFIX}"; characterline $LINECHAR $length } # Print a line of characters (e.g. `characterline '#' 32`) function characterline { char=$1 count=$2 for (( i = 0; i < $count; i++ )); do echo -n $char; done echo } # Main program # ------------ if [[ "$@" == "--help" ]]; then usage exit 0 fi # Parse shell arguments and set global variables while getopts ":hbsnp:l:" option; do case $option in h) usage exit 0 ;; b) STYLE=big ;; s) STYLE=singleline ;; n) STYLE=none ;; p) PREFIXCHAR="$OPTARG" ;; l) LINECHAR="$OPTARG" ;; :) echo "$BASENAME: option -$OPTARG requires an argument" >&2 echo "Try '$BASENAME --help' for more information." >&2 exit 1 ;; ?) echo "$BASENAME: invalid option: -$OPTARG" >&2 echo "Try '$BASENAME --help' for more information." >&2 exit 1 ;; esac done # Remove parsed options from arguments shift $(($OPTIND - 1)) # Set some global variables PREFIX= if [[ $PREFIXCHAR != '' ]]; then PREFIX="$PREFIXCHAR " fi # Print all files for file in $@; do print_file_with_header $file done