command line fun – spaces and arguments

I normally get to control most aspects of the program.  The most important yet trivial is the parameters that are being passed to the program.  Because I know what I want it is usually possible to coerce the calling script into giving me what I need.

Unfortunately there are always exceptions.  The most common problem is with dealing with normal users from the Windows world.  There are a lot of characters that they have no compunction about putting into a filename with the most common being the space.

If I am expecting a lot of files (and no spaces) then this extra space or six really can create some havoc. I would normally have a simple loop to iterate through my list.

#!/bin/bash

PARMS=$*

for item in $PARMS
do
  echo $item
  echo "(some processing goes here)"
  echo " "
done

Works great with commands that looks like any of the following

  • filename=receivables.txt
  • receivables.txt
  • -name=receivables.txt

When the space is introduced into the parameter value then the value gets split up with this type of processing.

> ./parser.sh filename=receivables.txt receivables.txt -name=receivables.txt "account receivables.txt"
filename=receivables.txt
(some processing goes here)
 
receivables.txt
(some processing goes here)
 
-name=receivables.txt
(some processing goes here)
 
account
(some processing goes here)
 
receivables.txt
(some processing goes here)

The bash shell actually does know that there are only four parameters that were passed, the problem is with this rather simplistic method of parsing.  Simply accessing the parameters directly will actually return the exact parameter including any spaces or special characters.

#!/bin/bash

filename1=$1
filename2=$2
filename3=$3
filename4=$4
filename11=$11

echo filename1 $filename1
echo filename2 $filename2
echo filename3 $filename3
echo filename4 $filename4
echo filename11 $filename11

It does work yet in a inflexible manner, besides this will work for the parameters up to 9 but not beyond that.  The easiest way would be to take the first parameter from the command line, process the file and then move to the next file.  The bash shell allows us to do that using the shift command.

#!/bin/bash

PARMS=$*

while [ $# -gt 0 ]
do
  filename=$1
  shift
  echo filename is "'$filename'"
  echo "(some processing goes here)"
  echo " "
done

In this way we simply continue taking arguments until there are no arguments left to take.

#!/bin/bash

DEBUG=0

idx=0
president=false

while [ $# -gt 0 ]
do
   item=$1
   if [ $DEBUG -ne 0 ]
   then
      echo ${idx}. $item
   fi

   VARIABLE=`echo $item | nawk -F=  '{print ($1)}'`
   VALUE=`echo $item | nawk -F=  '{print ($2)}'`

   case $VARIABLE in

      -president) president=true;;
      first) firstname=$VALUE;;
      last)  lastname=$VALUE;;
      addr)  address=$VALUE;;
      city)  city=$VALUE;;
      state)  state=$VALUE;;
      zip)  zipcode=$VALUE;;

      *) echo "unknown parm set ($VARIABLE/$VALUE)";;

   esac
   idx=$((idx + 1))
   shift
done

echo User Info
if [ $president == "true" ]
then
  echo President of the United States
fi
echo $firstname $lastname
echo $address
echo $city $state $zipcode

This method of parsing out the parameters supports both parameter=value as well as the more classic parameter preceded with a dash followed by a value.

> ./parser.sh first=bob last=johnson addr="123 main street" -president city=smallville state=IL zip=12321
User Info
President of the United States
bob johnson
123 main street
smallville IL 12321
>

To support the more classic method of parameter passing would require a few small changes, but that is left as an example to the reader.

This entry was posted in Command line and tagged , . Bookmark the permalink.