Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make Bash script exit and print error message if users invoke the script incorrectly

Script needed was

#!/bin/bash

# Check if there are two arguments
if [ $# -eq 2 ]; then
   # Check if the input file actually exists.
   if ! [[ -f "$1" ]]; then
     echo "The input file $1 does not exist."
     exit 1
   fi
else
   echo "Usage: $0 [inputfile] [outputfile]"
   exit 1
fi

# Run the command on the input file
grep -P "^[\s]*[0-9A-Za-z-]+.?[\s]*$" "$1" > "$2"

Edit, the script has changed to

grep -P "^[\s]*[0-9A-Za-z-]+.?[\s]*$" $*
if [ ! -f "$1" ]; then

  echo 'Usage: '
  echo
  echo './Scriptname inputfile > outputfile'
  exit 0

fi

invoking the script with no parameters gives no erros and sits blank

Usage: 

./Scriptname inputfile > outputfile

I have bit of code

grep -P "^[\s]*[0-9A-Za-z-]+.?[\s]*$" $*

This code pulls lines that have a single word on them and pumps the output to a new file, so for example

This is a multi word line
this
the above line is not
now
once again wrong

The output would be

This
now

The code works, users invoke the code using ./scriptname file > newfile

However, I am trying to expand the code to give users an error message if they invoke the script incorrectly.

For the error messange, I'm thinking of echoing something back like scriptname file_to_process > output_file.

I did try

if [incorrectly invoted unsure what to type]
echo $usage

exit 1
Usage="usage [inputfile] [>] [outputfile]

However I have had little luck. The code runs but does nothing if I invoke with just the script name. Also, if I invoke the script with just the scriptname and the input file, it will output the results instead of exiting with the error message.

Other ones I have tried are

if [ ! -n $1 ]; then

  echo 'Usage: '
  echo 
  echo './Scriptname inputfile > outputfile'
  exit 0

fi

Given replies I have received so far, my code now is

#!/bin/bash
grep -P "^[\s]*[0-9A-Za-z-]+.?[\s]*$" $*
if [ ! -f "$1" ]; then

  echo 'Usage: '
  echo 
  echo './Scriptname inputfile > outputfile'
  exit 0

fi

When invoking the script without an input file the script does nothing and has to be aborted with ctrl+c, still trying to get the echo of the invoke message.

like image 311
Ausghostdog Avatar asked Oct 19 '12 02:10

Ausghostdog


1 Answers

When you are invoking the script like ./scriptname file > newfile, the shell interprets file as the only argument to ./scriptname. This is because > is the standard output redirection operator.

I would like to propose 2 possible alternatives:


Alternative 1: Maybe you're can try passing it as 1 argument like this?
./scriptname 'file > newfile'

In that case one way to check the format would be

#!/bin/bash

# Check if the format is correct
if [[ $1 =~ (.+)' > '(.+) ]]; then
  # Check if the input file actually exists.
  if ! [[ -f "${BASH_REMATCH[1]}" ]]; then
    echo "The input file ${BASH_REMATCH[1]} does not exist!"
    exit 1
  fi
else
  echo "Usage: $0 \"[inputfile] [>] [outputfile]\""
  exit 1
fi

# Redirect standard output to the output file
exec > "${BASH_REMATCH[2]}"
# Run the command on the input file
grep -P "^[\s]*[0-9A-Za-z-]+.?[\s]*$" "${BASH_REMATCH[1]}"

Note: If you are checking whether the arguments are valid or not, it's generally better to run commands only after the checking is done.


Alternative 2: Passing 2 arguments like

./scriptname file newfile

The script looks like this

#!/bin/bash

# Check if there are two arguments
if [ $# -eq 2 ]; then
   # Check if the input file actually exists.
   if ! [[ -f "$1" ]]; then
     echo "The input file $1 does not exist."
     exit 1
   fi
else
   echo "Usage: $0 [inputfile] [outputfile]"
   exit 1
fi

# Run the command on the input file
grep -P "^[\s]*[0-9A-Za-z-]+.?[\s]*$" "$1" > "$2"
like image 107
doubleDown Avatar answered Oct 05 '22 17:10

doubleDown