LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Using GetOpts and error handling (https://www.linuxquestions.org/questions/programming-9/using-getopts-and-error-handling-4175713609/)

chrisqck 06-19-2022 05:27 AM

Using GetOpts and error handling
 
Hi All,

I learning bash scripting and this time I trying to write a script that accepts a folder path (-P) and a file name (-N) then check if this file exists in the folder path specified. I'm using /home/chrisqck/Scripting/sometextfile.txt to test the script.

I'm having a problem where if I run the script with -P then -N it will work beautifully. However if i swap the switches, -N first then -P the script will error out. I know there's a "logic flow" problem but for the life of me, i just can't figure out how else to do this. Is there a way for me to do for -N : If [[ -z $FolderPath ]] then "jump to -P then jump back to -N" else proceed with -N ? If not, how should i reqork the 'logic' of this script ?

Here is the script :

Code:

FolderPath=""  # Default to empty path
FileName=""    # Default to empty file name.

while getopts "P:N:H" opt ; do
  case $opt in
     
    P)  # Handles Folder Path
        if [[ -d $OPTARG ]]; then            # If folder path is valid...
                FolderPath=$OPTARG      # Set var $FolderPath to value of $OPTARG
        else
                      echo -e "\nError: Please enter a valid folder path.\nHint: Run FileLocate -H for Help."
                exit 1;       
        fi
        ;;

    N)  # Handles File name
       
        if [[ -f $FolderPath$OPTARG ]]; then        # Check if file name provided exists in folder.
                FileName=$OPTARG
                echo "File $OPTARG exists in folder $FolderPath"
        else
                echo -e "\nError: Please enter a valid file name. \nHint: Run FileLocate -H for Help."
                exit 1;
              fi
        ;;

    H)  # Show Help Menu - Quick Usage Guide.
        echo "FileLocate Usage Quick Guide"
        ;;

    ?)
        echo -e "\nError: Invalid option.\nHint: Run FileLocate -H for Help."
        ;;

    :)
        echo -e "\nError: No argument provided !!\nHint: Run FileLocate -H for Help."
        ;;

  esac

done


# To ensure that -P & - N are both entered
if [[ -z $FolderPath ]] || [[ -z $FileName ]]; then
        echo -e "\nError: Both -P and -N are MANDATORY !!!\nRun with FileLocate -H for Help" >&2
        exit 1;
fi


Any advice / guidance is much appreciated. Thanks in advance.

smallpond 06-19-2022 06:44 AM

only set the variables as you parse the options. Do the logic tests after all the options have been read.

michaelk 06-19-2022 06:48 AM

Your possible options are:
Use one option for both /path/filename
Do not check for a valid path/filename until after the while loop.

Since both P and N require arguments exit the program in the loop if no argument provided i.e. either at :) or ?)

pan64 06-19-2022 08:53 AM

yes, the general way is first check the arguments only, and validate them after the while loop.
Otherwise you may try shellcheck to help fix issues.

chrisqck 06-24-2022 10:35 PM

Hi All,

I've been tied up with other critical task the pst couple of days. Just wanna drop in and thank everyone for the recommendations and guidance. Will work on the script and update once done.

Much thanks ~!!! :D

teckk 06-25-2022 09:47 AM

Quote:

I'm having a problem where if I run the script with -P then -N it will work beautifully. However if i swap the switches, -N first then -P the script will error out.
This is what you are doing. You will need to do them in P N H order, or you won't get all of them in the output

test1.sh
Code:

#!/usr/bin/bash

while getopts "P:N:H" opt ; do
    case "$opt" in
        P) echo "P" ;;
       
        N) echo "N" ;;
       
        H) echo "H" ;;
    esac
done

Code:

bash ./test1.sh -P x -N x -H x
P
N
H

bash ./test1.sh -N x -H x -P x
N
H


This will get them in any order.

test2.sh
Code:

#!/usr/bin/bash

optstring='P:N:H:'

while getopts "$optstring" opt ; do
    case "$opt" in
        P) echo "P" ;;
       
        N) echo "N" ;;
       
        H) echo "H" ;;
       
        *) echo "Bad input"
    esac
done

Code:

bash ./test2.sh -N x -P x -H x
N
P
H

bash ./test2.sh -P x -N x -H x
P
N
H

bash ./test2.sh -H x -N x -P x
H
N
P

bash ./test2.sh -G x -N x -H x
./test2.sh: illegal option -- G
Bad input


teckk 06-25-2022 10:24 AM

Follow up.

test3.sh
Code:

#!/usr/bin/bash

optstring='P:p:N:n:H:h:'

while getopts "$optstring" opt ; do
    case "$opt" in
        [Pp]*) echo ""$opt" arg is > "$OPTARG"" ;;
       
        [Nn]*) echo ""$opt" arg is > "$OPTARG"" ;;
       
        [Hh]*) echo ""$opt" arg is > "$OPTARG"" ;;
       
        *) echo "Bad input"
    esac
done

Code:

bash ./test3.sh -N cow -P cat -H dog
N arg is > cow
P arg is > cat
H arg is > dog

bash ./test3.sh -H house -p cat -n dog
H arg is > house
p arg is > cat
n arg is > dog

bash ./test3.sh -p xx -H yy -N zz
p arg is > xx
H arg is > yy
N arg is > zz


chrisqck 06-28-2022 05:12 AM

Hi All,

Again, I want to thank everyone for the tips and guidance. This script I wanted to learn how to use GetOpts. The function of the script is simply to check and let the person running it know if a specific file exists in a specific folder. The biggest mistake I made, I've learnt, was trying to fit in too many things in the GetOpt. What I should've done was to use it to just get the arguments then assign it to the correct variable and proceed from there.


As the common practice in forums, I'm sharing my final script that I've been working on the couple of day. I'm sure someone here can make it even more efficient. As a newbie in this, I'm a little proud of that part that checks if the given path ends with "/" :D This has been an interesting lesson and I've learnt so much more than I thought I would.


Code:


FolderPath=""  # Default to empty path
FileName=""    # Default to empty file name.

# Function Help_Full - Full Help / User Guide. Note: Use when -h swicth is used with script.
function Help_Full () {
        echo -e "FILELOCATE(1)\t\t\tUsage Guide\n"
        echo -e "\033[1mUSAGE:\033[0m\n\t./FileLocate -p \"/path/to/folder\" -n \"FileName\"\n"
        echo -e "\033[1mDESCRIPTION:\033[0m\n\tScript to check if a specific File exists in a specific folder.\n"
        echo -e "\033[1m\t-p\033[0m\t\033[1mMandatory Option.\033[0m Specify folder path to be checked. Must end with "/" otherwise will result in error.\n"
        echo -e "\033[1m\t-n\033[0m\t\033[1mMandatory Option.\033[0m Specify file name to find.\n"
        echo -e "\033[1m\t-h\033[0m\tPrints this Quick Guide menu.\n\n"
        echo -e "Written By Chris Q. With Assistance From Jason L. - June 2022\n"       
        exit 0;
}


# Function Help_Quick - Quick Help / Guide. Note : Use in switches error message OR when script run without options.
function Help_Quick () {
        echo -e "\033[1mUSAGE: \033[0m./FileLocate.sh -p \"/path/to/folder\" -n \"Filename\".\n "
}




while getopts "p:n:h" opt;
do
  case $opt in
     
    p)  # Handles Folder Path argument.
              FolderPath=$OPTARG      # Set value of $FolderPath
        ;;

    n)  # Handles File name argument.
        FileName=$OPTARG        # Set value of $FileName
        ;;

    h)  # Show Help Menu / Usage Guide.
        Help_Full       
            ;;
    :)        # Handling Missing Mandatory Switches
        echo -e "\nError: Switches -p and -n requires argument.\n"
        Help_Quick       
              exit 1;
        ;;

    ?)        # Handling Invalid Option(s)
              echo -e "\nError: Invalid option.\n"
        Help_Quick
              exit 1;
        ;;

  esac

done


# To ensure that -P & - N are both entered

if [[ -z $FolderPath ]] || [[ -z $FileName ]]; then
        echo -e "Error: Switches -p and -n requires an argument !!!\n" >&2
        Help_Quick
        exit 1;
fi


# This section verifies folder path & file name is valid.

if [[ -d $FolderPath ]]; then            # If folder path is valid...
        i=$( echo "${FolderPath: -1}" )       
        if [[ $i != "/" ]]; then
                echo "Error: Folder Path must end with /"       
        else
                if [[ -f $FolderPath$FileName ]]; then               
                        echo "File $FileName exists in Folder $FolderPath !!!"
                        exit 0;       
                else       
                        echo "File $FileName does not exists in Folder $FolderPath !!!" 
                fi
                exit 0;
        fi       
else
        echo -e "\nError: Please enter a valid folder path.\n"
        Help_Quick
        exit 1;       
fi



All times are GMT -5. The time now is 06:44 PM.