Tips and tricks
The following sections expects that researchers are familiar
wth the Linux command line, vi
or
(vim
) editor. Any use of a username (such as
john
) should be substituted with the researcher's
own Michigan Tech ISO username.
Prior to using a shell script, researchers will need to change
its permission to at least 700
, if not
755
, via the chmod
command as
follows:
chmod 700 SCRIPT_NAME.sh
ARGUMENT
indicates a mandatory/required
argument for a given script, while [ARGUMENT]
indicates an optional argument.
Researchers may also clone the
Research Computing Tips repository
to get updated versions of these scripts.
Self-paced learning
BASH: Arithmetic (exponentiation)
#! /bin/bash # # BASH script for exponentiation (i.e., a raised to the power 'b'). # # Usage: # exponentiation.sh NUMBER1 NUMBER2 # Necessary variables EXPECTED_ARGS=2 # Check if two numbers are supplied at the command line. If not, print an # error message (help text) and exit if [ $# -ne $EXPECTED_ARGS ] then echo echo " Usage: `basename $0` NUMBER1 NUMBER2" echo " e.g.: `basename $0` 4 2" echo " `basename $0` -4 2.25" echo exit fi # Store the arguments A=$1 B=$2 # Validate A and B NUMERIC_INPUT='^-?[0-9]+([.][0-9]+)?$' if ! [[ $A =~ $NUMERIC_INPUT ]] then echo echo " NUMBER1 is invalid" echo exit fi NUMERIC_INPUT='^-?[0-9]+?$' if ! [[ $B =~ $NUMERIC_INPUT ]] then echo echo " NUMBER2 is invalid (non-integer)" echo exit fi # Arithmetic (exponentiation) C=`echo "$A ^ $B" | bc -l` # Print to screen echo echo " NUMBER1 (A) : $A" echo " NUMBER2 (B) : $B" echo " C = A ^ B : $C" echo
BASH: Arithmetic (divide two numbers)
#! /bin/bash # # BASH script to divide two given numbers. # # Usage: # division.sh NUMBER1 NUMBER2 # Necessary variables EXPECTED_ARGS=2 # Check if two numbers are supplied at the command line. If not, print an # error message (help text) and exit if [ $# -ne $EXPECTED_ARGS ] then echo echo " Usage: `basename $0` NUMBER1 NUMBER2" echo " e.g.: `basename $0` 4 2" echo " `basename $0` -4 2.25" echo exit fi # Store the arguments A=$1 B=$2 # Validate A and B NUMERIC_INPUT='^-?[0-9]+([.][0-9]+)?$' if ! [[ $A =~ $NUMERIC_INPUT ]] then echo echo " NUMBER1 is invalid" echo exit fi if ! [[ $B =~ $NUMERIC_INPUT ]] then echo echo " NUMBER2 is invalid" echo exit fi if [ $B -eq 0 ] then echo echo " NUMBER2 cannot be zero" echo exit fi # Arithmetic (division) C=`echo "$A / $B" | bc -l` # Print to screen echo echo " NUMBER1 (A) : $A" echo " NUMBER2 (B) : $B" echo " C = A / B : $C" echo
BASH: Arithmetic (multiply two numbers)
#! /bin/bash # # BASH script to multiply two given numbers. # # Usage: # multiplication.sh NUMBER1 NUMBER2 # Necessary variables EXPECTED_ARGS=2 # Check if two numbers are supplied at the command line. If not, print an # error message (help text) and exit if [ $# -ne $EXPECTED_ARGS ] then echo echo " Usage: `basename $0` NUMBER1 NUMBER2" echo " e.g.: `basename $0` 4 2" echo " `basename $0` -4 2.25" echo exit fi # Store the arguments A=$1 B=$2 # Validate A and B NUMERIC_INPUT='^-?[0-9]+([.][0-9]+)?$' if ! [[ $A =~ $NUMERIC_INPUT ]] then echo echo " NUMBER1 is invalid" echo exit fi if ! [[ $B =~ $NUMERIC_INPUT ]] then echo echo " NUMBER2 is invalid" echo exit fi # Arithmetic (multiplication) C=`echo "$A * $B" | bc -l` # Print to screen echo echo " NUMBER1 (A) : $A" echo " NUMBER2 (B) : $B" echo " C = A * B : $C" echo
BASH: Arithmetic (subtract two numbers)
BASH: Arithmetic (add two numbers)
#! /bin/bash # # BASH script to add two given numbers. # # Usage: # addition.sh NUMBER1 NUMBER2 # Necessary variables EXPECTED_ARGS=2 # Check if two numbers are supplied at the command line. If not, print an # error message (help text) and exit if [ $# -ne $EXPECTED_ARGS ] then echo echo " Usage: `basename $0` NUMBER1 NUMBER2" echo " e.g.: `basename $0` 4 2" echo " `basename $0` -4 2.25" echo exit fi # Store the arguments A=$1 B=$2 # Validate A and B NUMERIC_INPUT='^-?[0-9]+([.][0-9]+)?$' if ! [[ $A =~ $NUMERIC_INPUT ]] then echo echo " NUMBER1 is invalid (contains non-numeric charcaters)" echo exit fi if ! [[ $B =~ $NUMERIC_INPUT ]] then echo echo " NUMBER2 is invalid (contains non-numeric charcaters)" echo exit fi # Arithmetic (addition) C=`echo "$A + $B" | bc -l` # Print to screen echo echo " NUMBER1 (A) : $A" echo " NUMBER2 (B) : $B" echo " C = A + B : $C" echo
BASH: Read (and parse) a file one line at a time
#! /bin/bash # # BASH script to read a given file, one line at a time, and parse the line # to accomplish a desired task. # # This particular script assumes that any line that is empty or any line that # begins with # is less useful, and as such ignores them. The file used to # demonstrate the script has four fields -- student name and her/his score in # three assignments -- separated by |. The desired task is to display the # student name, individual assignment score as well as the cumulative score, # average score, and an associated letter grade. # # Usage: # read_file_line_by_line.sh FILENAME # Necessary variables EXPECTED_ARGUMENTS=1 # Check if a file is supplied at the command line. If not, print an error # message (help text) and exit if [ $# -ne $EXPECTED_ARGUMENTS ] then echo echo " Usage: `basename $0` FILENAME" echo " e.g.: `basename $0` students.txt" echo exit fi # Function to convert score into letter grade score2grade() { # Input local original_score=${1} # Sanitized score (strip off all non-numeric characters) sanitized_score=`echo "$original_score" | sed 's/[^0-9\.]//g'` # Assign a letter grade to sanitized score case $sanitized_score in 100.00) echo "A" ;; 9[0-9].[0-9][0-9]) echo "A" ;; 8[0-9].[0-9][0-9]) echo "B" ;; 7[0-9].[0-9][0-9]) echo "C" ;; 6[0-9].[0-9][0-9]) echo "D" ;; [1-5][0-9].[0-9][0-9]) echo "F" ;; [0-9].[0-9][0-9]) echo "F" ;; esac } # Save the filename FILENAME="$1" # Check if file exists. If not, print an error message (help text) and exit if [ ! -e "$FILENAME" ] then echo echo " $FILENAME does not exist." echo " Exiting." echo exit fi # Check if file has zero size. If yes, print an error message (help text) # and exit FILE_SIZE=$(du $FILENAME | awk '{print $1}') if [ "$FILE_SIZE" -eq 0 ] then echo echo " $FILENAME exists but is empty." echo " Exiting." echo exit fi # Check if file has non-zero size but has any useful information. If not, # print an error message (help text) and exit NON_BLANK_LINES=`sed '/^ *#/d;s/#.*//' $FILENAME | sed '/^$/d' | wc -l` if [ "$NON_BLANK_LINES" -eq 0 ] then echo echo " $FILENAME exists and is not empty but has no useful information." echo " Exiting." echo exit fi # Create a temporary sanitized file SANITIZED_FILENAME="${FILENAME}_$$" sed '/^ *#/d;s/#.*//' $FILENAME | sed '/^$/d' > $SANITIZED_FILENAME # Formatted output i=0 echo echo " --------------------------------------------------------------" printf " %-2s %-20s %3s %3s %3s %-5s %-7s %-5s\n" "##" "Student" "#1" "#2" "#3" "Total" "Average" "Grade" echo " --------------------------------------------------------------" # Read through the sanitized file one line at a time exec<$SANITIZED_FILENAME while read student_info do # Increment the index 'i' i=`expr $i + 1` STUDENT_NAME=`echo $student_info | awk -F '|' '{ print $1 }' | sed 's/^[ \t]*//;s/[ \t]*$//'` ASSIGNMENT_1=`echo $student_info | awk -F '|' '{ print $2 }' | sed 's/^[ \t]*//;s/[ \t]*$//'` ASSIGNMENT_2=`echo $student_info | awk -F '|' '{ print $3 }' | sed 's/^[ \t]*//;s/[ \t]*$//'` ASSIGNMENT_3=`echo $student_info | awk -F '|' '{ print $4 }' | sed 's/^[ \t]*//;s/[ \t]*$//'` TOTAL_SCORE=`echo "$ASSIGNMENT_1 + $ASSIGNMENT_2 + $ASSIGNMENT_3" | bc` AVERAGE_SCORE=`echo "scale=2; $TOTAL_SCORE/3" | bc` LETTER_GRADE=`score2grade $AVERAGE_SCORE` printf " %2d %-20s %3d %3d %3d %5d %7s %5s\n" "$i" "$STUDENT_NAME" "$ASSIGNMENT_1" "$ASSIGNMENT_2" "$ASSIGNMENT_3" "$TOTAL_SCORE" "$AVERAGE_SCORE" "$LETTER_GRADE" done # Formatted output echo " --------------------------------------------------------------" echo # Delete the temporary sanitized file rm -f $SANITIZED_FILENAME
BASH: List files with a given name in a given location
#! /bin/bash # # BASH script to list all files in a given directory that have PART_OF_THE_NAME # as part of their name. # # If option -h is specified with any other option, -h takes precedence over # all other options. # # Usage: # list_file_by_name.sh -h # list_file_by_name.sh [-l LOCATION] [-f PART_OF_THE_NAME] # Function to display error message (help text) show_help() { echo echo " Usage: `basename $0` -h" echo " `basename $0` [-l LOCATION] [-f PART_OF_THE_NAME]" echo echo " e.g. `basename $0`" echo " `basename $0` -f txt" echo " `basename $0` -l /research/john" echo " `basename $0` -l /research/john -f txt" echo exit } # -l and -f must have parameter values # -h doesn't need a parameter value while getopts :l:f:h option do case "$option" in # -h h) show_help ;; # -l l) # If -l is specified with no value, display help if [ -n $OPTARG ] then LOCATION="$OPTARG" else show_help fi ;; # -f f) # If -f is specified with no value, display help if [ -n $OPTARG ] then NAME="$OPTARG" else show_help fi ;; esac done # If NAME is empty, then assume any file type if [ -z $NAME ] then NAME="*" fi # If LOCATION is empty, then assume present working directory if [ -z $LOCATION ] then LOCATION=`pwd` fi # List all files that that match the criteria echo echo " Location : $LOCATION" echo " File name contains : $NAME" echo find $LOCATION -iname "*$NAME*" | sort echo
BASH: Reminder utility (Part #2: search through the notes)
#! /bin/bash # # BASH script to search through quick notes stored using 'remember_me.sh'. # # Usage: # remind_me.sh SEARCH_STRING # Necessary variables MINIMUM_ARGS=1 # Check if a string supplied at the command line. If not, # print an error message (help text) and exit if [ $# -lt $MINIMUM_ARGS ] then echo echo " Usage: `basename $0` SEARCH_STRING" echo " e.g.: `basename $0` michigan" echo " `basename $0` michigan tech" echo exit fi # Necessary variables REMEMBER="$HOME/.remember" SEARCH_STRING="$@" # Search through the stored notes (case insensitive search) and display all # matching entries with time stamp grep -B1 -i "$SEARCH_STRING" $REMEMBER
BASH: Reminder utility (Part #1: save the note)
#! /bin/bash # # BASH script to store quick (i.e., one line) notes for a later reference. # Use 'remind_me.sh' to search through the stored quick notes. # # Usage: # remember_me.sh # Necessary variables EXPECTED_ARGS=0 # Check if the script is called with no options. If not, print an error # message (help text) and exit if [ $# -ne $EXPECTED_ARGS ] then echo echo " Usage: `basename $0`" echo exit fi # Necessary variables REMEMBER="$HOME/.remember" DATE_TIME=`date -R` # Prompt the user for a note to remembered echo "Enter a quick note to remember [press ENTER key when done]" read NOTE2REMEMBER NOTE2REMEMBER_SANITIZED=`echo ${NOTE2REMEMBER} | sed 's/^[ \t]*//;s/[ \t]*$//'` # Record the note along with the time stamp echo "# $DATE_TIME" >> $REMEMBER echo "$NOTE2REMEMBER_SANITIZED" >> $REMEMBER echo
BASH: Time conversion (seconds to human readable format)
#! /bin/bash # # BASH script to convert seconds into human readable format. # # Usage: # seconds2hrf.sh SECONDS # Necessary variables EXPECTED_ARGS=1 # Check if number of seconds is supplied at the command line. If not, # print an error message (help text) and exit if [ $# -ne $EXPECTED_ARGS ] then echo echo " Usage: `basename $0` SECONDS" echo " e.g.: `basename $0` 1234" echo exit fi # Save the number of seconds SECONDS="$1" # Convert seconds to days, hours, minutes and seconds DD=`echo "$SECONDS/86400" | bc` HH=`echo "$SECONDS%86400/3600" | bc` MM=`echo "$SECONDS%3600/60" | bc` SS=`echo "$SECONDS%60" | bc` # Print the result to the screen printf "%d:%02d:%02d:%02d\n" $DD $HH $MM $SS
Gnuplot: Iterative plot (multiple datasets)
# iterative_plot_datasets.gnu # # Usage: # gnuplot iterative_plot_datasets.gnu set terminal pngcairo dashed size 1280,800 enhanced font 'Helvetica,24' set output "iterative_plot_datasets.png" set title "Iterative plot of multiple data sets (Amdahl's Law)" set xlabel "# of processors" set ylabel "Speed up" set yrange [0:21] set logscale x 2 set key left top set key autotitle columnhead set grid plot for [i=1:7] 'dataset_'.i.'.dat' using 1:2 with lines lw 1
iterative_plot_datasets.png
generate_datasets.sh
dataset_1.dat |
dataset_2.dat |
dataset_3.dat |
dataset_4.dat |
dataset_5.dat |
dataset_6.dat |
dataset_7.dat
Gnuplot: Iterative plot (sine function; filled/translucent)
# iterative_plot_sine_filled.gnu # # Usage: # gnuplot iterative_plot_sine_filled.gnu set terminal pngcairo size 1280,800 enhanced font 'Helvetica,24' set output "iterative_plot_sine_filled.png" set title "Iterative plot (filled/translucent)" set xlabel "x" set ylabel "sin(x*n)/n" set xrange [0.00:6.28] noreverse nowriteback set yrange [-1.1:1.1] set grid set style fill transparent solid 0.25 noborder set sample 1000 plot for [n=1:5] sin(x*n)/n notitle with filledcurves
Gnuplot: Iterative plot (sine function; line)
# iterative_plot_sine_lines.gnu # # Usage: # gnuplot iterative_plot_sine_lines.gnu set terminal pngcairo size 1280,800 enhanced font 'Helvetica,24' set output "iterative_plot_sine_lines.png" set title "Iterative plot (lines)" set xlabel "x" set ylabel "sin(x*n)/n" set xrange [0.00:3.00] noreverse nowriteback set yrange [-0.6:0.6] set grid set style data lines set sample 500 plot for [n=2:10] sin(x*n)/n notitle lw (13-n)/2
Gnuplot: Iterative plot (Bessel function; filled)
# filled_curves_bessel.gnu # # Usage: # gnuplot filled_curves_bessel.gnu set terminal pngcairo size 1280,800 enhanced font 'Helvetica,24' set output "filled_curves_bessel.png" set title "Iterative plot (filled/translucent)" set xlabel "x" set ylabel "J_n(x)" set xrange [0:25] set yrange [-0.5:1] set grid set style fill transparent solid 0.25 noborder set style function filledcurves y1=0 set sample 5000 besj2(x) = 2*1/x * besj1(x) - besj0(x) besj3(x) = 2*2/x * besj2(x) - besj1(x) besj0_(x) = x<5 ? besj0(x) : 1/0 plot besj0(x) fs transparent solid 0.80 noborder t 'J_0(x)' , \ besj1(x) fs transparent solid 0.60 noborder t 'J_1(x)' , \ besj2(x) fs transparent solid 0.40 noborder t 'J_2(x)' , \ besj3(x) fs transparent solid 0.20 noborder t 'J_3(x)'
Gnuplot: Filled curves (Probabilty intensity; translucent)
# filled_curves_probability.gnu # # Usage: # gnuplot filled_curves_probability.gnu set terminal pngcairo size 1280,800 enhanced font 'Helvetica,24' set output "filled_curves_probability.png" set title "Filled curves (translucent)" set xlabel "x" set ylabel "Probability Intensity f(v)" set grid set key top right set style fill transparent solid 0.5 noborder f(v,T)=4/sqrt(pi*T**3)*exp(-v**2/T)*v**2 set sample 500 plot [0:5] f(x,0.1) with filledcurves x1 title "T=0.1",\ f(x,1) with filledcurves x1 title "T=1.0",\ f(x,5) with filledcurves x1 title "T=5.0"
Gnuplot: Filled curves (Gaussian function; solid)
# filled_curves_gaussian.gnu # # Usage: # gnuplot filled_curves_gaussian.gnu set terminal postscript eps enhanced color "Helvetica" 24 set output "filled_curves_gaussian.eps" set size 2.0,2.0 set title "Filled curves (solid)" set xlabel "x" set ylabel "Gaussian" set style fill solid 1.0 noborder set style function filledcurves y1=0 set clip two Gauss(x,mu,sigma) = 1./(sigma*sqrt(2*pi)) * exp( -(x-mu)**2 / (2*sigma**2) ) d1(x) = Gauss(x, 0.5, 0.75) d2(x) = Gauss(x, 1.0, 2.00) d3(x) = Gauss(x, 4.0, 3.00) set xrange [-6:10] set yrange [0:1] unset colorbox set key top left Left reverse samplen 1 plot d1(x) fs solid 1.0 lc rgb "forest-green" title "{/Symbol m} = 0.5; {/Symbol s} = 0.5", \ d2(x) lc rgb "gold" title "{/Symbol m} = 2.0; {/Symbol s} = 1.0", \ d3(x) lc rgb "red" title "{/Symbol m} = -1.0; {/Symbol s} = 2.0"
Gnuplot: Curve fit with error bar
# curve_fit_error_bar.gnu # # Gnuplot instructions to plot the data contained in # curve_fit_error_bar.dat with error bars. # # Usage: # gnuplot curve_fit_error_bar.gnu set terminal postscript eps enhanced color "Helvetica" 24 set output "curve_fit_error_bar.eps" set size 2.0,2.0 set title "Linear curve fit and error bar" set xlabel "# of processors" set ylabel "Measured quantity" set samples 100 set xrange [0:18] set grid fit a*x + b 'curve_fit_error_bar.dat' using 1:2:3 via a,b plot 'curve_fit_error_bar.dat' title 'Error bar' with errorbars lw 2, a*x + b title 'Curve fit' lw 2 lt 1 lc 3
curve_fit_error_bar.dat | curve_fit_error_bar.eps | curve_fit_error_bar.log
Gnuplot: Curve fit (cubic)
# curve_fit_cubic.gnu # # Gnuplot instructions to plot the data contained in # curve_fit.dat. # # Usage: # gnuplot curve_fit_cubic.gnu set terminal postscript eps enhanced color "Helvetica" 24 set output "curve_fit_cubic.eps" set size 2.0,2.0 set title "Curve fit (cubic)" set xlabel "# of processors" set ylabel "Measured quantity" set samples 100 set xrange [0:18] set grid set key bottom right fit a*x*x*x + b*x*x + c*x + d 'curve_fit.dat' using 1:2 via a,b,c,d plot 'curve_fit.dat' using 1:2 title 'Measured data' with points lc 4 pt 5, a*x*x*x + b*x*x + c*x + d title 'Curve fit' lw 2 lt 1 lc 8
Gnuplot: Curve fit (quadratic)
# curve_fit_quadratic.gnu # # Gnuplot instructions to plot the data contained in # curve_fit.dat. # # Usage: # gnuplot curve_fit_quadratic.gnu set terminal postscript eps enhanced color "Helvetica" 24 set output "curve_fit_quadratic.eps" set size 2.0,2.0 set title "Curve fit (quadratic)" set xlabel "# of processors" set ylabel "Measured quantity" set samples 100 set xrange [0:18] set grid set key bottom right fit a*x*x + b*x + c 'curve_fit.dat' using 1:2 via a,b,c plot 'curve_fit.dat' using 1:2 title 'Measured data' with points pt 5, a*x*x + b*x + c title 'Curve fit' lw 2 lt 1 lc 5
curve_fit.dat | curve_fit_quadratic.eps | curve_fit_quadratic.log
Gnuplot: Curve fit (linear)
# curve_fit_linear.gnu # # Gnuplot instructions to plot the data contained in # curve_fit.dat. # # Usage: # gnuplot curve_fit_linear.gnu set terminal postscript eps enhanced color "Helvetica" 24 set output "curve_fit_linear.eps" set size 2.0,2.0 set title "Curve fit (linear)" set xlabel "# of processors" set ylabel "Measured quantity" set samples 100 set xrange [0:18] set grid set key bottom right fit a*x + b 'curve_fit.dat' using 1:2 via a,b plot 'curve_fit.dat' using 1:2 title 'Measured data' with points pt 5, a*x + b title 'Curve fit' lw 2 lt 1 lc 5
Gnuplot: Mathematical functions (trigonometric)
# trigonometric_functions.gnu # # Usage: # gnuplot trigonometric_functions.gnu set terminal postscript eps enhanced color "Helvetica" 24 set output "trigonometric_functions.eps" set size 2.0,2.0 set title "Trigonometric functions" set xlabel "x" set ylabel "sin(x), arctan(x), cos(arctan(x))" set xrange [0:18] set grid set key outside plot [-15:15] sin(x) title "sin(x)" with linesp lt 8 pt 5, \ atan(x) title "arctan(x)" with linesp lt 3 pt 4, \ cos(atan(x)) title "cos(arctan(x))" with impulses lt 9
Gnuplot: 3D plot projected onto a 2D surface
# 3d_plot_2d_projection.gnu # # Gnuplot instructions to plot the data contained in # 3d_plot_2d_projection.dat. # # Usage: # gnuplot 3d_plot_2d_projection.gnu set terminal postscript eps enhanced color "Helvetica" 24 set output "3d_plot_2d_projection.eps" set size 2.0,2.0 set title "2 dimensional heat map" set xlabel "# of atoms" set ylabel "# of processors" set ticslevel 0.2 set grid set dgrid3d set hidden3d set pm3d map set nokey splot '3d_plot_2d_projection.dat' using 1:2:3 with pm3d
Gnuplot: 3D plot
# 3d_plot.gnu # # Gnuplot instructions to plot the data contained in 3d_plot.dat. # # Usage: # gnuplot 3d_plot.gnu set terminal postscript eps enhanced color "Helvetica" 24 set output "3d_plot.eps" set size 2.0,2.0 set title "3 dimensional plot" set xlabel "# of atoms" set ylabel "# of processors" # set zlabel "Wall Time (seconds)" set ticslevel 0.2 set grid set dgrid3d 30,30 set hidden3d set pm3d set nokey # Plot splot '3d_plot.dat' using 1:2:3 with pm3d
Gnuplot: Multiple plots using multiple data sets from a single file
# multiple_data_sets_single_file.gnu # # Gnuplot instructions to plot the data contained in # multiple_data_sets_single_file.dat. # # Usage: # gnuplot multiple_data_sets_single_file.gnu set terminal postscript eps enhanced color "Helvetica" 24 set output "multiple_data_sets_single_file.eps" set size 2.0,2.0 set title "Multiple sets of data points from one file" set xlabel "# of processors" set ylabel "Time (seconds)" set xrange [0:18] set grid plot 'multiple_data_sets_single_file.dat' using 1:2 title "# of atoms = 6" with linesp lt 1 pt 5, \ 'multiple_data_sets_single_file.dat' using 1:3 title "# of atoms = 8" with linesp lt 2 pt 4, \ 'multiple_data_sets_single_file.dat' using 1:4 title "# of atoms = 10" with linesp lt 3 pt 3
multiple_data_sets_single_file.dat | multiple_data_sets_single_file.eps
Gnuplot: Single plot using a single data set from a single file
# single_data_set_single_file.gnu # # Gnuplot instructions to plot the data contained in # single_data_set_single_file.dat. # # Usage: # gnuplot single_data_set_single_file.gnu set terminal postscript eps enhanced color "Helvetica" 24 set output "single_data_set_single_file.eps" set size 2.0,2.0 set title "One set of data points from one file" set xlabel "# of processors" set ylabel "Time (seconds)" set xrange [0:18] set grid plot 'single_data_set_single_file.dat' using 1:2 title "# of atoms = 10" with linesp lt 1 pt 5
single_data_set_single_file.dat | single_data_set_single_file.eps
BASH: Check file usefulness
#! /bin/bash # # BASH script to check if a file has useful information. # Applications include checking if a file contains non-comment characters # before proceeding ahead with parsing/processing it. # # Usage: # check_file_usefulness.sh FILENAME # Necessary variables EXPECTED_ARGS=1 # Check if a filename is supplied at the command line. If not, print # an error message (help text) and exit if [ $# -ne $EXPECTED_ARGS ] then echo echo " Usage: `basename $0` FILENAME" echo " e.g.: `basename $0` sample.tex" echo " `basename $0` sample.txt" echo exit fi # Save the filename export FILENAME="$1" # Check if file has non-zero size but has any useful information. If not, # print an error message (help text) and exit # '%' is the comment character in MATLAB and LaTeX. Replace it with the # appropriate comment character for a different language ('#' for shell # scripting and PHP, etc.) NON_BLANK_LINES=`sed '/^ *%/d;s/%.*//' $FILENAME | sed '/^$/d' | wc -l` if [ "$NON_BLANK_LINES" -eq 0 ] then echo echo " $FILENAME exists and is not empty but has no useful information." echo " Exiting." echo exit fi
BASH: Check file size
#! /bin/bash # # BASH script to check if a file has non-zero size. # Applications include checking if a file has non-zero size, along with # existence check (check_file_existence.sh), before proceeding ahead with # parsing/processing it. # # Usage: # check_file_size.sh FILENAME # Necessary variables EXPECTED_ARGS=1 # Check if a filename is supplied at the command line. If not, print # an error message (help text) and exit if [ $# -ne $EXPECTED_ARGS ] then echo echo " Usage: `basename $0` LATEX_FILENAME" echo " e.g.: `basename $0` sample.tex" echo exit fi # Save the filename export FILENAME="$1" # Check if the file has zero size. If yes, print an error message (help text) # and exit FILE_SIZE=$(du $FILENAME | awk '{print $1}') if [ "$FILE_SIZE" -eq 0 ] then echo echo " $FILENAME exists but is empty." echo " Exiting." echo exit fi
BASH: Check file existence
#! /bin/bash # # BASH script to check if a file exists. # Applications include checking if a file exists before proceeding ahead with # parsing/processing it. # # Usage: # check_file_existence.sh FILENAME # Necessary variables EXPECTED_ARGS=1 # Check if a filename is supplied at the command line. If not, print # an error message (help text) and exit if [ $# -ne $EXPECTED_ARGS ] then echo echo " Usage: `basename $0` FILENAME" echo " e.g.: `basename $0` sample.tex" echo " `basename $0` sample.txt" echo exit fi # Save the filename export FILENAME="$1" # Check if the file exists. If not, print an error message (help text) and exit if [ ! -e "$FILENAME" ] then echo echo " $FILENAME does not exist." echo " Exiting." echo exit fi
BASH: LaTeX+BibTeX compilation
#! /bin/bash # # BASH script to run LaTeX+BibTeX and convert the DVI to PDF. # It also removes unncessary files. # # Usage: # lbtex.sh LATEX_FILENAME # Necessary variables EXPECTED_ARGS=1 # Check if a LaTeX file is supplied at the command line. If not, print # an error message (help text) and exit if [ $# -ne $EXPECTED_ARGS ] then echo echo " Usage: `basename $0` LATEX_FILENAME" echo " e.g.: `basename $0` sample.tex" echo exit fi # Save the filename and extract the basename (i.e., without .tex) export FILENAME="$1" export BASENAME=`echo "$FILENAME" | awk -F '.' '{ print $1 }'` # Run LaTeX twice, BibTeX twice, LaTeX twice and convert DVI to PDF. # If need be, convert DVI to PS and then PS to PDF echo echo " Running LaTeX on $FILENAME and convert to PDF" latex $FILENAME &> /dev/null latex $FILENAME &> /dev/null bibtex $BASENAME &> /dev/null bibtex $BASENAME &> /dev/null latex $FILENAME &> /dev/null latex $FILENAME &> /dev/null dvipdf $BASENAME.dvi $BASENAME.pdf # Delete unnecessary files echo " ... Done ... Now deleting unnecessary files" rm -f $BASENAME.aux $BASENAME.out $BASENAME.toc rm -f $BASENAME.lof $BASENAME.lot $BASENAME.log rm -f $BASENAME.blg $BASENAME.lot $BASENAME.bbl echo " ... Done" echo
BASH: LaTeX compilation
#! /bin/bash # # BASH script to run LaTeX and convert the DVI to PDF. # It also removes unncessary files. # # Usage: # ltex.sh LATEX_FILENAME # Necessary variables EXPECTED_ARGS=1 # Check if a LaTeX file is supplied at the command line. If not, print # an error message (help text) and exit if [ $# -ne $EXPECTED_ARGS ] then echo echo " Usage: `basename $0` LATEX_FILENAME" echo " e.g.: `basename $0` sample.tex" echo exit fi # Save the filename and extract the basename (i.e., without .tex) export FILENAME="$1" export BASENAME=`echo "$FILENAME" | awk -F '.' '{ print $1 }'` # Run LaTeX twice and convert DVI to PDF. # If need be, convert DVI to PS and then PS to PDF echo echo " Running LaTeX on $FILENAME and converting to PDF" latex $FILENAME &> /dev/null latex $FILENAME &> /dev/null dvipdf $BASENAME.dvi $BASENAME.pdf # Delete unnecessary files echo " ... Done ... Now deleting unnecessary files" rm -f $BASENAME.aux $BASENAME.out $BASENAME.toc rm -f $BASENAME.lof $BASENAME.lot $BASENAME.log echo " ... Done" echo
BASH: Spell check
#! /bin/bash # # BASH script to check the spelling of a given (set of) word(s). # # Usage: # spell_check.sh WORD1 [WORD2] ... [WORDn] # Necessary variables MINIMUM_ARGUMENTS=1 # Check if a word (or more) is supplied at the command line. If not, print # an error message (help text) and exit if [ $# -lt $MINIMUM_ARGUMENTS ] then echo echo " Usage: `basename $0` WORD1 [WORD2] ... [WORDn]" echo " e.g.: `basename $0` spelling" echo " `basename $0` spelling spleling wonder" echo exit fi # Variables SPELL="ispell -l" # Formatted output i=1 echo echo " ---------------------------------" echo " ## Word Spelling" echo " ---------------------------------" # Check the spelling of each supplied word for word do if [ -z $(echo $word | $SPELL) ] then printf " %02d %-14s %s\n" "$i" "$word" "Correct" else printf " %02d %-14s %s\n" "$i" "$word" "Incorrect" fi # Increment the index 'i' i=`expr $i + 1` done # Formatted output echo " ---------------------------------" echo
BASH: Root check
#! /bin/bash # # BASH script to check if the currently logged in user is root. # Applications include scripts that need to be run only as root. # # Usage: # root_check.sh # Check if the currently logged in user is root using the value of # UID variable. If not, print an error message (help text) and exit if [ $UID != 0 ] then echo echo " Not logged in as root! Exiting." echo exit fi
BASH: Validate IP address
#! /bin/bash # # BASH script to check if a given string is an IP address (IPv4). # # Usage: # validate_ip_address.sh IP_ADDRESS # Necessary variables EXPECTED_ARGUMENTS=1 # Check if an IP address is supplied at the command line. If not, print an # error message (help text) and exit if [ $# -ne $EXPECTED_ARGUMENTS ] then echo echo " Usage: `basename $0` IP_ADDRESS" echo " e.g.: `basename $0` 123.456.789.012" echo exit fi # Variables IP_ADDRESS="$1" # Check if the supplied IP address is in the format ###.####.###.#### # i.e., if IP address is a set of 4 integers separated by '.' if [[ $IP_ADDRESS =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] then # Save the current/default Internal Field Separator OIFS=$IFS # Set the default Internal Field Separator to '.' IFS='.' # Split the string IP_ADDRESS into an array using the new IFS as the # field separator OCTETS=($IP_ADDRESS) # Restore the Internal Field Separator to its default value IFS=$OIFS # Check if each element of the array is less than 255 if [[ ${OCTETS[0]} -le 255 && ${OCTETS[1]} -le 255 \ && ${OCTETS[2]} -le 255 && ${OCTETS[3]} -le 255 ]] then echo echo " $IP_ADDRESS is valid" echo else echo echo " $IP_ADDRESS is invalid" echo fi else echo echo " $IP_ADDRESS is invalid" echo fi
BASH: Remote server status
#! /bin/bash # # BASH script to ping a given remote server identified by an IP address. # Applications include using this as a preliminary test of 'remote server # being alive' before attempting to transfer files (e.g., data backup via # cron jobs, etc.). # # Potential enhancements include validating the IP address. # # Usage: # remote_server_status.sh IP_ADDRESS # Necessary variables EXPECTED_ARGUMENTS=1 # Check if an IP address is supplied at the command line. If not, print an # error message (help text) and exit if [ $# -ne $EXPECTED_ARGUMENTS ] then echo echo " Usage: `basename $0` IP_ADDRESS" echo " e.g.: `basename $0` 123.456.789.012" echo exit fi # Variables SERVER="$1" PING_COUNT=20 # Ping the remote server N times quietly # Select the line that contains "packet loss" PING_REQUESTS=`ping -c $PING_COUNT -q $SERVER | \ grep "packet loss"` # Count the number of pings (KNOCK_KNOCK), number of responses (WHO_IS_THERE) # and create a status for the network and/or the remote server KNOCK_KNOCK=`echo $PING_REQUESTS | \ awk -F ' ' '{ print $1 }'` WHO_IS_THERE=`echo $PING_REQUESTS | \ awk -F ' ' '{ print $4 }'` if [ $WHO_IS_THERE -eq $KNOCK_KNOCK ] then STATUS="Excellent" else # 75% packets received if [ $WHO_IS_THERE -le `echo "scale=0; $KNOCK_KNOCK * (3/4)" | bc` ] then STATUS="Average" fi # 50% packets received if [ $WHO_IS_THERE -le `echo "scale=0; $KNOCK_KNOCK * (2/4)" | bc` ] then STATUS="Poor" fi # 25% packets received if [ $WHO_IS_THERE -le `echo "scale=0; $KNOCK_KNOCK * (1/4)" | bc` ] then STATUS="Very poor" fi # 0 packets received if [ $WHO_IS_THERE -eq 0 ] then STATUS="Down" fi fi # Print the information echo echo " ---------------------------------------------------" echo " -- Ping -- Server/Network" echo " Remote server Sent Recd status" echo " ---------------------------------------------------" printf " %-15s %02d %02d %s\n" "$SERVER" "$KNOCK_KNOCK" "$WHO_IS_THERE" "$STATUS" echo " ---------------------------------------------------" echo
BASH: List IP address
#! /bin/bash # # BASH script to list all network interfaces and the associated IP address. # # Usage: # list_ip_address.sh # Necessary variables EXPECTED_ARGUMENTS=0 # Check if there is any argument supplied at the command line. If yes, print # an error message (help text) and exit if [ $# -ne $EXPECTED_ARGUMENTS ] then echo echo " Usage: `basename $0`" echo exit fi # List all network interfaces # 'netstat -i' provides the list # Delete the first two lines using 'sed' # Extract the first column using 'awk' NETWORK_INTERFACES=`netstat -i | \ sed '1,2d' | \ awk -F ' ' '{ print $1 }'` # Formatted output i=1 echo echo " ----------------------------------------" echo " ## Interface IP Address and Subnet " echo " ----------------------------------------" # IP address associated with each network interface for x in $NETWORK_INTERFACES do # 'ip' lists all information associated with a # given network interface # Retain only the line that has "inet " using 'grep' # Extract the secont column using 'awk' IP_ADDRESS_SUBNET=`ip addr show $x | \ grep "inet " | \ awk -F ' ' '{ print $2 }'` # Print the information printf " %02d %-9s %s\n" "$i" "$x" "$IP_ADDRESS_SUBNET" # Increment the index 'i' i=`expr $i + 1` done # Formatted output echo " ----------------------------------------" echo
BASH: Compile Gnuplot
#! /bin/bash # # BASH script to download and compile GNUPlot. When completed, it will also # create a symbolic link in $HOME/bin/ # # Usage: # compile_gnuplot.sh GNUPLOT_VERSION # Necessary variables EXPECTED_ARGUMENTS=1 # Check if more/less than the expected number of arguments have been supplied # at the command line. If yes, print an error message (help text) and exit if [ $# -ne $EXPECTED_ARGUMENTS ] then echo echo " Usage: `basename $0` GNUPLOT_VERSION" echo " e.g.: `basename $0` 4.6.4" echo exit fi # Additional variables GNUPLOT_VERSION="$1" COMPILER="gcc" COMPILER_VERSION="4.4.6" CC="gcc" CXX="g++" FC="gfortran" F77="gfortran" TODAY=`/bin/date +"%Y%m%d_%H%M%S"` # Installation specific variables GNUPLOT_SOURCE="gnuplot-$GNUPLOT_VERSION.tar.gz" GNUPLOT_INSTALL="$HOME/local/gnuplot/$GNUPLOT_VERSION/$COMPILER/$COMPILER_VERSION" GNUPLOT_WEBSITE="http://sourceforge.net/projects/gnuplot/files/gnuplot" # Check if the source code (gnuplot-GNUPLOT_VERSION.tar.gz) already exists in # the current folder. If yes, use it. If not, download it if [ ! -e "${GNUPLOT_SOURCE}" ] then wget $GNUPLOT_WEBSITE/$GNUPLOT_VERSION/$GNUPLOT_SOURCE fi # Create the installation location (must be writable) mkdir -p $GNUPLOT_INSTALL # Create a temporary folder and extract GNUPlot source code mkdir ./tmp cd ./tmp tar -zxvf ../$GNUPLOT_SOURCE # Run configure, make clean, make, make install cd gnuplot-${GNUPLOT_VERSION}/ ./configure --prefix=$GNUPLOT_INSTALL 2>&1 | tee configure_$TODAY.txt make clean 2>&1 | tee make-clean_$TODAY.txt make 2>&1 | tee make_$TODAY.txt make install 2>&1 | tee make-install_$TODAY.txt # Remove ./tmp cd ../../ \rm -r ./tmp # Create symbolic link in $HOME/bin mkdir -p $HOME/bin cd $HOME/bin ln -sf $GNUPLOT_INSTALL/bin/gnuplot gnuplot echo
BASH: Input validation
#! /bin/bash # # BASH script to validate user input. Each function makes sure a user's input # is alphabetical, numeric or alphanumeric. # # Technique is to strip off all non-desired characters from the string # (user input) using 'sed' ('tr' and 'awk' may also be used to accomplish this # task). If the stripped version is identical to the original string, then the # user input is valid (exit value: 0); invalid otherwise (exit value: 1). # # A recommended way is to store these functions in a separate file (say, # functions.sh) and source them for general use by more than one shell script. # # Usage: # input_validation.sh # Necessary variables EXPECTED_ARGUMENTS=0 # Check if more than the expected number of arguments have been supplied at # the command line. If yes, print an error message (help text) and exit if [ $# -ne $EXPECTED_ARGUMENTS ] then echo echo " Usage: `basename $0`" echo exit fi # Function #1: alphabetic input validate_alphabetic() { # User input local original_string=${1} # Strip off all non-alphabetic characters from original_string sanitized_string=`echo "$original_string" | sed 's/[^a-zA-Z]//g'` # Compare original_string and sanitized_string, and return a value if [ "$original_string" != "$sanitized_string" ] then # Invalid user input return 1 else # Valid user input return 0 fi } # Function #1: alphabetic input # Function #2: numeric input validate_numeric() { # User input local original_string=${1} # Strip off all non-numeric characters from original_string sanitized_string=`echo "$original_string" | sed 's/[^0-9]//g'` # Compare original_string and sanitized_string, and return a value if [ "$original_string" != "$sanitized_string" ] then # Invalid user input return 1 else # Valid user input return 0 fi } # Function #2: numeric input # Function #3: alphanumeric input validate_alphanumeric() { # User input local original_string=${1} # Strip off all non-alphanumeric characters from original_string sanitized_string=`echo "$original_string" | sed 's/[^a-zA-Z0-9]//g'` # Compare original_string and sanitized_string, and return a value if [ "$original_string" != "$sanitized_string" ] then # Invalid user input return 1 else # Valid user input return 0 fi } # Function #3: alphanumeric input # Accept user input echo echo -n " User input: " read USER_INPUT echo # Uncomment only one of the three validations below: # Alphabetic validation # Note: '[ ... ]' is not a part of 'if' syntax by default; # Using 'if [ ! validate_alphabetic "$USER_INPUT" ]' will result in errors if ! validate_alphabetic "$USER_INPUT" then echo " Invalid (contains non-alphabetic charcaters)" echo exit else echo " Valid" echo fi # Numeric validation # Note: '[ ... ]' is not a part of 'if' syntax by default; # Using 'if [ ! validate_numeric "$USER_INPUT" ]' will result in errors if ! validate_numeric "$USER_INPUT" then echo " Invalid (contains non-numeric charcaters)" echo exit else echo " Valid" echo fi # Alphanumeric validation # Note: '[ ... ]' is not a part of 'if' syntax by default; # Using 'if [ ! validate_alphanumeric "$USER_INPUT" ]' will result in errors. if ! validate_alphanumeric "$USER_INPUT" then echo " Invalid (contains non-alphanumeric charcaters)" echo exit else echo " Valid" echo fi
BASH: Smart extract
#! /bin/bash # # BASH script to automagically uncompress different kinds of compresed # files/folders based on the filename extension. # # Usage: # smart_extract.sh COMPRESSED_FILENAME # Necessary variables EXPECTED_ARGUMENTS=1 # Check if a compressed filename is supplied at the command line. If not, # print an error message (help text) and exit if [ $# -ne $EXPECTED_ARGUMENTS ] then echo echo " Usage: `basename $0` COMPRESSED_FILENAME" echo " e.g.: `basename $0` file.tar.gz" echo " `basename $0` file.zip" echo " `basename $0` file.bz2" echo exit fi # Variables COMPRESSED_FILENAME="$1" # Uncompress the file based on the filename extension if [ -f $COMPRESSED_FILENAME ] then case $COMPRESSED_FILENAME in *.tar) tar -xvf $COMPRESSED_FILENAME ;; *.tgz) tar -xvzf $COMPRESSED_FILENAME ;; *.tar.gz) tar -xvzf $COMPRESSED_FILENAME ;; *.tbz2) tar -xvjf $COMPRESSED_FILENAME ;; *.tar.bz2) tar -xvjf $COMPRESSED_FILENAME ;; *.gz) gunzip $COMPRESSED_FILENAME ;; *.bz2) bunzip2 $COMPRESSED_FILENAME ;; *.zip) unzip $COMPRESSED_FILENAME ;; *) echo " '$COMPRESSED_FILENAME' file type unknown" ;; esac else echo echo " '$COMPRESSED_FILENAME' is not a regular file" echo fi
BASH: Replace space with underscore in a file name
#! /bin/bash # # BASH script to replace one or more spaces in file names with an underscore. # One may create, for testing purposes, files with space in their name as # # touch "file name 1.txt" # touch "file name 2.txt" # touch "file name 3.txt" # # and so on. # # Usage: # replace_space_with_underscore.sh # Necessary variables EXPECTED_ARGUMENTS=0 # Check if there is any argument supplied at the command line. If yes, print # an error message (help text) and exit if [ $# -ne $EXPECTED_ARGUMENTS ] then echo echo " Usage: `basename $0`" echo exit fi # Loop through the list of files (use *.txt or *.dat, etc. to limit the # selection to specific file types) and replace space with an underscore - if # and only if the new file name (with underscores) does not already exist echo for x in * do y=$(echo "$x" | tr ' ' '_') if [ -e $y ] then printf " %25s --x--> %-25s (already exists)\n" "$x" "$y" else printf " %25s -----> %-25s\n" "$x" "$y" mv "$x" "$y" fi done echo
BASH: Count the number of occurances of each word in a file
#! /bin/bash # # BASH script to count the number of occurances of each word in a specified # file and print the results. # # If option -h is specified with any other option, -h takes precedence over # all other options. # # Usage: # word_count -h # word_count.sh -F FILENAME # # For testing purposes, one may download a book in plain text format from # Project Gutenberg website using the command: # # wget http://www.gutenberg.org/files/44362/44362-0.txt # Function to display error message (help text) show_help() { echo echo " Usage: `basename $0` -h" echo " `basename $0` -F FILENAME" echo echo " e.g. `basename $0`" echo " `basename $0` -F 44362-0.txt" echo exit } # -F must have a parameter value # -h doesn't need a parameter value while getopts :F:h option do case "$option" in # -h h) show_help ;; # -F F) # If -F is specified with no value, display help if [ -n $OPTARG ] then FILENAME="$OPTARG" else show_help fi ;; # If nothing is specified, display help *) show_help ;; esac done # Validate FILENAME # Check if FILENAME variable is empty if [ -z $FILENAME ] then show_help fi # Check if the file exists if [ ! -e "$FILENAME" ] then echo echo " $FILENAME does not exit." echo " Exiting." echo exit fi # Check if file has non-zero size FILESIZE=$(du $FILENAME | awk '{ print $1 }'); if [ "$FILESIZE" -eq 0 ] then echo echo " $FILENAME exists but is empty." echo " Exiting." echo exit fi # Check if the file has any useful information in spite of # non-zero size NON_BLANK_LINES=`sed '/^$/d' $FILENAME | wc -l` if [ "$NON_BLANK_LINES" -eq 0 ] then echo echo " $FILENAME exists and is not empty but " echo " has no useful information." echo " Exiting." echo exit fi # Count the words and print to the screen echo echo " --------------------------------------" echo " ##### Word Count" echo " --------------------------------------" # egrep with the given options retains only words, numbers # and words with numbers egrep -o "\b[[:alnum:]]+\b" $FILENAME | \ sort | \ uniq -c | \ sort -n | \ awk '{ printf(" %5d %-20s %4d\n", NR, $2, $1); }' echo " --------------------------------------" echo
BASH: List files larger than a given size in a given location
#! /bin/bash # # BASH script to list all files in a given directory that are equal to or # larger than a certain set size (expressed in MB). # # If option -h is specified with any other option, -h takes precedence over # all other options. # # Usage: # list_file_by_size.sh -h # list_file_by_size.sh [-l LOCATION] [-s SIZE_IN_MB] # Function to display error message (help text) show_help() { echo echo " Usage: `basename $0` -h" echo " `basename $0` [-l LOCATION] [-s SIZE_IN_MB]" echo echo " e.g. `basename $0`" echo " `basename $0` -s 100" echo " `basename $0` -l /research/john" echo " `basename $0` -l /research/john -s 10" echo exit } # -l and -s must have parameter values # -h doesn't need a parameter value while getopts :l:s:h option do case "$option" in # -h h) show_help ;; # -l l) # If -l is specified with no value, display help if [ -n $OPTARG ] then LOCATION="$OPTARG" else show_help fi ;; # -s s) # If -s is specified with no value, display help if [ -n $OPTARG ] then SIZE="$OPTARG" else show_help fi ;; esac done # If SIZE is empty, then assume 2 MB limit if [ -z $SIZE ] then SIZE="2" fi # Convert size (in MB) to kB SIZE_IN_KB=`echo "$SIZE * 1024" | bc` # If LOCATION is empty, then assume present working directory if [ -z $LOCATION ] then LOCATION=`pwd` fi # Necessary variables KILOBYTE="1024" MEGABYTE=`echo "$KILOBYTE * 1024" | bc` GIGABYTE=`echo "$MEGABYTE * 1024" | bc` # List all files that are at least 2 MB in $LOCATION using 'find', 'awk' and # 'sed' commands echo echo " Location : $LOCATION" echo " Min. size : $SIZE MB" echo find $LOCATION -name '*' -size +${SIZE_IN_KB}k -ls | \ awk --assign=MB="$MEGABYTE" \ '{ filesize+=$7; printf(" %5d MB %s\n", $7/MB, $11); }' | \ sort -nr echo
BASH: Sum of numbers (with getopts
)
#! /bin/bash # # BASH script to add a series of given numbers and print the sum. Works for # integers and non-integers alike. 'getopts' does not support "long option" # format (i.e., --help, --begin, --step, --end, etc.). # # If option -h is specified with any other option, -h takes precedence over # all other options. # # Usage: # sum_numbers_getopts.sh -h # sum_numbers_getopts.sh -B BEGIN [-S STEP] -E END # Function to display error message (help text) show_help() { echo echo " Usage: `basename $0` -h" echo " `basename $0` -B BEGIN [-S STEP] -E END" echo echo " e.g. `basename $0` -B 1 -S 2 -E 100" echo " `basename $0` -B 1 -E 100" echo exit } # The 'getopts' command is built into the BASH shell. It looks a lot like # 'getopt', but 'getopts' command works on the existing shell parameter # variables sequentially. It processes the parameters it detects in the # command line one at a time each time it’s called. When it runs out of # parameters, it exits with an exit status greater than zero. This makes it # suitable for using in loops to parse all of the parameters on the command # line. The syntax of the 'getopts' command is: # # getopts optstring variable # # One should list valid option letters in the 'optstring', along with a colon # if the option letter requires a parameter value. To suppress error messages, # one should start the 'optstring' with a colon. The 'getopts' command places # the current parameter in the variable defined in the command line ('option' # in this case). # # The OPTARG environment variable contains the value to be used if an option # requires a parameter value. The OPTIND environment variable contains the # value of the current location within the parameter list where 'getopts' # left off. This allows one to continue processing other command line # parameters after finishing the options. # -B, -S and -E must have parameter values # -h doesn't need a parameter value while getopts :B:E:S:h option do case "$option" in # -h h) show_help ;; # -B B) # If -B is specified with no value, display help if [ -n $OPTARG ] then BEGIN="$OPTARG" else show_help fi ;; # -S S) # If -S is specified with no value, display help if [ -n $OPTARG ] then STEP="$OPTARG" else show_help fi ;; # -E E) # If -E is specified with no value, display help if [ -n $OPTARG ] then END="$OPTARG" else show_help fi ;; # If nothing is specified, display help *) show_help ;; esac done # Check to make sure that BEGIN, STEP and END have appropriate values if [ -z $BEGIN ] || [ -z $END ] then show_help fi # If STEP is empty, then assume steps of 1 if [ -z $STEP ] then STEP="1" fi # Generate the sequence of numbers using 'seq' # Calcuate and print the sum using 'awk' SUM=`seq $BEGIN $STEP $END | \ awk '{ sum += $1 } END { print sum }'` # Print to screen echo echo " Begin (-B) : $BEGIN" echo " Step (-S) : $STEP" echo " End (-E) : $END" echo " Sum : $SUM" echo
BASH: Sum of numbers
#! /bin/bash # # BASH script to add a series of given numbers and print the sum. Works for # integers and non-integers alike. # # Usage: # sum_numbers.sh BEGIN [STEP] END # Necessary variables MINIMUM_ARGUMENTS=2 MAXIMUM_ARGUMENTS=3 # Check if the user has supplied less than the minimum OR more than the # maximum number of arguments at the command line. If yes, print an error # message (help text) and exit if [ $# -lt $MINIMUM_ARGUMENTS ] || [ $# -gt $MAXIMUM_ARGUMENTS ] then echo echo " Usage: `basename $0` BEGIN [STEP] END" echo " e.g.: `basename $0` 1 1 10" echo " `basename $0` 1 2 10" echo " `basename $0` 1 10" echo exit fi # If the third argument is missing, then assume increments of 1 if [ -z $3 ] then BEGIN="$1" STEP="1" END="$2" else BEGIN="$1" STEP="$2" END="$3" fi # Generate the sequence of numbers using 'seq' # Calcuate and print the sum using 'awk' SUM=`seq $BEGIN $STEP $END | \ awk '{ sum += $1 } END { print sum }'` # Print to screen echo echo " Begin : $BEGIN" echo " Step : $STEP" echo " End : $END" echo " Sum : $SUM" echo
BASH: Login counter
#! /bin/bash # # BASH script to count and display usernames in descending order of the number # of successful login attempts. # # Usage: # login_counter.sh # Necessary variables EXPECTED_ARGUMENTS=0 # Check if there is any argument supplied at the command line. If yes, print # an error message (help text) and exit if [ $# -ne $EXPECTED_ARGUMENTS ] then echo echo " Usage: `basename $0`" echo exit fi # Date/Time when the record keeping began # System's own record of login attempts using 'last' # Ignore everything but the very last line using 'tail' # Select the last field (date and time) using 'awk' with # "wtmp begins " as the field separator RECORD_START_DATE=`last | \ tail -1 | \ awk -F 'wtmp begins ' '{ print $NF }'` # Print to the screen echo echo " Hostname : `hostname`" echo " Start date : $RECORD_START_DATE" echo # System's own record of login attempts using 'last' # Delete all blank lines using 'sed' # Ignore all lines that contain 'wtmp' # Select the first field (username) using 'awk' using # space as the field separator # Sort the first column using 'sort' # Count the number of duplicate lines using 'uniq' # Reverse sort the list using 'sort' to get the # descending order last | \ sed '/^$/d' | \ grep -v "wtmp" | \ awk -F ' ' '{ print $1 }' | \ sort | \ uniq -c | \ sort -nr echo
BASH: Hello, User!
#! /bin/bash # # BASH script to print "Hello, USERNAME!" to the screen, along the hostname, # current date/time and current working directory. USERNAME is the username # of currently logged in user. # # Usage: # hello_user_regular.sh # Print to the terminal echo echo " Hello, $USER!" echo " Hostname : `hostname`" echo " Date/Time : `date -R`" echo " Location : `pwd -P`" echo
#! /bin/bash # # BASH script to print "Hello, USERNAME!" to the screen, along with the # hostname and current date/time iff a username is supplied at the command # line. # # Usage: # hello_user_special.sh USERNAME # Necessary variables EXPECTED_ARGUMENTS=1 # Check if the username is supplied at the command line. If not, print an # error message (help text) and exit if [ $# -ne $EXPECTED_ARGUMENTS ] then echo echo " Usage: `basename $0` USERNAME" echo " e.g.: `basename $0` john" echo exit fi # Variables USERNAME="$1" # Print to the terminal echo echo " Hello, $USERNAME!" echo " Hostname : `hostname`" echo " Date/Time : `date -R`" echo
#! /bin/bash # # BASH script to print "Hello, USERNAME!" to the screen, along with the # hostname and current date/time. USERNAME is the username supplied at the # command line; if not supplied, use the currently logged in user's username. # # Usage: # hello_user_premium.sh [USERNAME] # Necessary variables MAXIMUM_ARGUMENTS=1 # Check if more than the maximum number of arguments have been supplied at the # command line. If yes, print an error message (help text) and exit if [ $# -gt $MAXIMUM_ARGUMENTS ] then echo echo " Usage: `basename $0` [USERNAME]" echo " e.g.: `basename $0` john" echo " `basename $0`" echo exit fi # Check if the username is supplied at the command line. If yes, set USERNAME # to supplied value; if not, set it to username of currently logged in user if [ $# -eq $MAXIMUM_ARGUMENTS ] then USERNAME="$1" else USERNAME="$USER" fi # Print to the terminal echo echo " Hello, $USERNAME!" echo " Hostname : `hostname`" echo " Date/Time : `date -R`" echo