#!/bin/sh -u # Print file system information about all command line arguments. #------------------------------------------------------------ # Syntax: # $0 pathnames... #------------------------------------------------------------ # Purpose: # Print file system information about all command line arguments. # Method: # Issue an error message and exit 2 if there are no arguments. # Prompt and read two "range" integers from the user. # For each argument on the command line, output a six-character flag # followed by the pathname. Print summary information at the end. # # The flag is set to '??????' for nonexistent pathnames. # # For existing pathnames, the flag is structured as follows: # First char: D for directory # F for file # - for anything else # Second char: R if readable by me # - if not # Third char: W if writable by me # - if not # Fourth char: X if executable by me # - if not # Fifth char: one space # Sixth char: ? if not a file or directory # Z if a zero-size file/directory # S if a small file/directory # M if a medium file/directory # L if a large file/directory # # The range integers determine whether a pathname is small/medium/large: # small: the size (in bytes) is smaller than smallest range integer # medium: between or equal to the two range integers (inclusive) # larg: the size (in bytes) is larger than the largest range integer # # After processing all the pathnames, output these summary statistics: # - a count of missing pathnames # - a count of files # - a count of directories # - a count of "other" pathnames (none of the above) # # Print an error message and exit 2 on any errors. # Exit 1 if any command line argument was nonexistent. # Exit 0 if every command line argument existed. #------------------------------------------------------------- # Student Name: Ian! D. Allen # Algonquin EMail Address: alleni # Student Number: 000-000-000 # Course Number: CST8129 # Lab Section Number: 010 # Professor Name: Ian! D. Allen # Assignment Name/Number/Date: Assignment #1, script 3, due November 7 # Comment: This is a sample assignment label. # see http://idallen.com/teaching/assignment_standards.html #------------------------------------------------------------- # Set standard search path and umask. # PATH=/bin:/usr/bin ; export PATH umask 022 # Function definitions go here ------------------------------------ # The IsNumeric function tests its argument to see if it is a valid number. # It sets the return/exit status to zero if it is a number, to 1 if not. # IsNumeric () { # Make sure this function is called with exactly one argument. # if [ $# -ne 1 ] ; then echo 1>&2 "$0: Function IsNumeric expects one argument; found $# ($*)" exit 2 fi # The expr command sets a return code of 2 on a syntax error or # bad (non-numeric) input. Throw away all the output and errors; # look at the return status only. # [ "$1" = '-' ] && return 1 # compensate for non-number bug in expr expr 0 + "$1" >/dev/null 2>&1 # expr sets return code test "$?" -ne 2 # set return code to 0 if expr return is not 2 } # End of function definitions --------------------------------------- # Exit 2 if there are no arguments. # if [ $# -eq 0 ] ; then echo 1>&2 "$0: Expecting pathname arguments; found none" exit 2 fi # Prompt (always on standard error) and read the two range integers. # echo 1>&2 "Enter two file/directory size range integers:" read lower upper || exit $? # Optional: Echo the user's input back to the user. # echo "You entered range integers '$lower' and '$upper'" # Optional: Print a nice message if any input number was empty. # if [ -z "$lower" -o -z "$upper" ] ; then echo 1>&2 "$0: Empty range integer(s); nothing done. Bye." exit 2 fi # Validate each input integer to make sure it is numeric. # if ! IsNumeric "$lower" ; then echo 1>&2 "$0: First range integer '$lower' is not numeric; exiting" exit 2 fi if ! IsNumeric "$upper" ; then echo 1>&2 "$0: Second range integer '$upper' is not numeric; exiting" exit 2 fi # Having validated the two range variables as integers, we no longer need # to quote these variables in the rest of the script. # Sort the two range integers for later use. # Make sure they are both non-negative (0 or larger). # if [ $lower -gt $upper ] ; then tmp=$lower lower=$upper upper=$tmp fi if [ $lower -lt 0 ] ; then echo 1>&2 "$0: range integer '$lower' is less than zero; nothing done" exit 2 fi # Keep counts of what kinds of pathnames we find. # missingcount=0 # missing pathnames filecount=0 # file pathnames dircount=0 # directory pathnames othercount=0 # other pathnames # Loop for all the command line arguments. # Initialize and append file system summary information to a $flag variable. # Print the flag and the pathname at the end of the loop body. # for pathname do # Initialize the flag to empty for this pathname. # flag='' if [ ! -e "$pathname" ] ; then # Nonexistent pathnames get six ?????? in the flag; that is all. # flag="${flag}??????" let ++missingcount else # Existing pathnames get tested to set the six characters. # This code would benefit from being moved into a function so # that the ELSE isn't so long! # First character (pathname type): one of [FD-] # if [ -f "$pathname" ] ; then char="F" let ++filecount elif [ -d "$pathname" ] ; then char="D" let ++dircount else char="-" let ++othercount fi flag="${flag}$char" # Second character (readable): one of [R-] # if [ -r "$pathname" ] ; then char="R" else char="-" fi flag="${flag}$char" # Third character (writable): one of [W-] # if [ -w "$pathname" ] ; then char="W" else char="-" fi flag="${flag}$char" # Fourth character (executable): one of [X-] # if [ -x "$pathname" ] ; then char="X" else char="-" fi flag="${flag}$char" # Fifth character: is always a space # flag="${flag} " # Sixth and last character (size rank): one of [?ZSML] # if [ ! -f "$pathname" -a ! -d "$pathname" ] ; then # if not a file and not a directory, just use ? for the size # char="?" else # Files and directories get the size ranked. # Get the size in bytes from the output of the ls command. # Make sure to use "ls -d" to list the directory itself. # size=$( ls -ld "$pathname" | awk '{print $5}' ) # Optional: # Test $size to make sure the command substitution worked. # The substitution might fail if a command is missing or # if system process or memory resources are low. # if ! IsNumeric "$size" ; then echo 1>&2 "$0: size integer '$size' for '$pathname'" \ "is not numeric; exiting" exit 2 fi # Classify the size against zero and the two range integers. # if [ $size -eq 0 ] ; then char="Z" elif [ $size -lt $lower ] ; then char="S" elif [ $size -le $upper ] ; then char="M" else char="L" fi fi flag="${flag}$char" fi # The flag now has six characters in it. # Output the flag followed by the pathname from the command line. # echo "$flag $pathname" done # The loop is finished: # Output the summary information about the pathnames we processed. # echo " " echo "Missing pathnames: $missingcount" echo "Pathnames that were files: $filecount" echo "Pathnames that were directories: $dircount" echo "Other kinds of pathnames: $othercount" # Return 1 if any pathnames were missing (if we counted any missing pathnames). # if [ $missingcount -ne 0 ] ; then return=1 else return=0 fi exit $return