Jump to content

Mandatory script arguments...A better way?


Recommended Posts

I have this script and I want to make the options -i /path/to/dir and -o /path/to/dir mandatory. This is how I've done it (yes, I know there's already rsync and it probably does what I'm doing better):

#/bin/bash

 

# Copyright 2005 Steve Scrimpshire (fibonacci@semperphi.com)

#

# This program is free software; you can redistribute it and/or modify

# it under the terms of the GNU General Public License as published by

# the Free Software Foundation; either version 2 of the License, or

# (at your option) any later version.

#

# This program is distributed in the hope that it will be useful,

# but WITHOUT ANY WARRANTY; without even the implied warranty of

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

# GNU General Public License for more details.

#

# You should have received a copy of the GNU General Public License

# along with this program; if not, write to the Free Software

# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

 

 

function funchelp(){

  echo "Usage: $0 -i /path/to/first/dir -o /path/to/second/dir"

  echo "      -v Be verbose"

  echo "      -h See this help message"

  exit;

  }

 

# We need arguments. Can't run the script not knowing what the two directories are. 

if [[ ! $@ ]]

then

echo -n "Enter the full path to the first dir: "

read indir

echo -n "Enter the full path to the second dir: "

read outdir

fi

 

# Check what options were passed

while getopts "hi:o:v" option; do

  case ${option} in

      i) indir=${OPTARG};; # first

      o) outdir=${OPTARG};; # second

      v) verbose="1";;

      h|*) scripthelp="1";;

    esac   

done 

 

if [ $scripthelp ]

then

funchelp

fi

 

# Didn't have the -i option. Give them another chance to enter it

if [ ! $indir ]

then

echo -n "Enter the full path to the first dir: "

read indir

fi

 

# Didn't have the -o option. Give them another chance to enter it

if [ ! $outdir ]

then

echo -n "Enter the full path to the second dir: "

read outdir

fi

 

# They had three chances to enter the directories. Complain and exit

if [ -z $indir -o -z $outdir ]

then

funchelp

fi

 

if [ ! -d $indir -a ! -d $outdir ]

then

echo "Neither one of those directories exists. Are you nuts?"

exit

fi

 

# Directory passed by -i does not exist or is not a directory

if [ ! -d $indir ]

then

echo "$indir does not exist or does not describe the path to a directory. Would you like to create it? (y/N):"

read create

  if [[ $create == "y" ]]

  then

    if [ -e $indir ]

    then

    echo "I'm sorry, but there is already a file with that name, so I can't create the directory. I have to go now."

    exit

    fi

  mkdir $indir

  let "created = 1"

  else

  exit

  fi

fi

 

# Directory passed by -o does not exist or is not a directory

if [ ! -d $outdir ]

then

  if [[ $created == "1" ]]

  then

  echo "$outdir does not exist or does not describe the path to a directory."

  exit

  else

  echo "$outdir does not exist or does not describe the path to a directory. Would you like to create it? (y/N):"

  read create

      if [[ $create == "y" ]]

      then

        if [ -e $outdir ]

        then

        echo "I'm sorry, but there is already a file with that name, so I can't create the directory. I have to go now."

        exit

        fi

      mkdir $outdir

      else

      exit

      fi

  fi

fi

 

# They entered the same directory for both -i and -o

if [[ $indir == "$outdir" ]]

then

echo "Those two entries are the same directory...come back when you're serious."

exit;

fi

 

# We need the the field separator to be newline and not space

old_IFS=$IFS

IFS=$'\n'

 

 

cd $outdir                                    # Change directory to the second directory

 

 

usbdirs=( $(tree -difa) )                      # Grab the full path to all the subdirectories into the array $usbdirs

element_count=${#usbdirs[@]}                  # How many elements in the array?

index=0                                      # Initialize the counter

 

 

while [ "$index" -lt "$element_count" ]      # We want to loop over the array, stopping when we reach the last element

do

  if [ ${usbdirs[$index]} != "" ]            # $(tree -dif) grabs blank lines, but they are not directories, so ignore them

  then

    if [ -d ${usbdirs[$index]} ]            # $(tree -dif) also grabs a line with the total # of directories, but it is not a dir

    then

    tester="${usbdirs[$index]}"              # Simplify the variable for use in the substitution

    testerz="${tester//.\//$(pwd)/}"        # The 'full path' from $(tree -dif) replaces pwd with . so set it back

      if [ ${usbdirs[$index]} == "." ]

        then

        testerz="${tester//./$(pwd)}"

        fi

    testerZ="${tester//.\//}"

      if [ ! -e "$indir/$testerZ" ]   

      then 

          if [ $verbose ]

          then

          echo "$testerz exists, but $indir/$testerZ does not, so I will create $indir/$testrZ"

  echo "Making directory $indir/$testerZ"

  fi

      mkdir "$indir/$testerZ"

  if [ $verbose ]

  then

  echo "Done"

  fi

      fi

      if [ $verbose ]

then

echo "cd-ing to $testerz"

fi

    cd "$testerz"

    usbfiles="$(ls -A)";

    for usbname in $usbfiles

    do

      if [[ "$usbname" != *.old ]]

        then

          if [ -f "$usbname" ]

          then

          mvdir=$indir/$testerZ/$(basename "$usbname");

            if [ -e $mvdir ]

            then

                if [ $mvdir -nt "$usbname" ]

                then

                  if [ $verbose ]

                  then

            echo "$mvdir is newer than $usbname, so I am going to cp $mvdir to $usbname."

            echo "Removing ${usbname}.old}"

            fi

  rm -f "${usbname}.old"

    if [ $verbose ]

    then

    echo "Done."

    echo "Moving $usbname to ${usbname}.old for a backup."

            fi

  mv "$usbname" "${usbname}.old"

            if [ $verbose ]

    then

    echo "Done."

    echo "Copying $mvdir to $usbname, preserving permissions."

    fi

                cp -p "$mvdir" "$usbname"

    if [ $verbose ]

    then

    echo "Done."

                  fi

  elif [ $mvdir -ot "$usbname" ]

  then

    if [ $verbose ]

    then

    echo "$usbname is newer than $mvdir, so I am going to cp $usbname to $mvdir."

            echo "Removing ${mvdir}.old"

    fi

  rm -f "${mvdir}.old"

    if [ $verbose ]

    then

    echo "Done."

    echo "Moving $mvdir to ${mvdir}.old for a backup."

            fi

  mv "$mvdir" "${mvdir}.old"

    if [ $verbose ]

    then

    echo "Done"

    echo "Copying $usbname to $mvdir"

            fi

  cp -p "$usbname" "$mvdir"

    if [ $verbose ]

    then

    echo "Done"

    fi

  else

    if [ $verbose ]

    then

    echo "These two files are the same age, so I will do nothing."

                  fi

  fi

            else

  if [ $verbose ]

  then

  echo "$mvdir does not exist, so I'll just copy $usbname to $mvdir"

                fi

            cp -p "$usbname" "$mvdir"

                if [ $verbose ]

        then

  echo "Done"

                fi 

      fi 

          fi

else

  if [ $verbose ]

  then

  echo "$usbname ended in .old, so I skipped it. Duh. Don't want to have a bunch of *.old.old.old files hanging around."

  fi

fi

    done

    fi

  fi

cd $outdir

let "index = $index + 1"

done

 

cd $indir

localdirs=( $(tree -difa) )

element_count=${#localdirs[@]}

index=0

 

while [ "$index" -lt "$element_count" ]

do

        if [ ${localdirs[$index]} != "" ]

    then

    if [ -d ${localdirs[$index]} ]

    then

        tester="${localdirs[$index]}"

        testerz="${tester//.\//$(pwd)/}"

        if [ ${localdirs[$index]} == "." ]

        then

                      testerz="${tester//./$(pwd)}"

        fi

        testerZ="${tester//.\//}"

#        testerZ="${tester//^./}"

        if [ ! -e "$outdir/$testerZ" ]   

              then

            if [ $verbose ]

      then

            echo "$testerz exists, but $outdir/$testerZ does not, so I will create $outdir/$testrZ"

      echo "Making directory $outdir/$testerZ"

      fi

      mkdir "$outdir/$testerZ"

      if [ $verbose ]

      then

      echo "Done"

      fi

              fi

        if [ $verbose ]

        then

        echo "cd-ing to $testerz"

        fi

        cd "$testerz"

                      localfiles="$(ls -A)";

                      for localname in $localfiles

                      do

                      if [[ "$localname" != *.old ]]

        then

        if [ -f "$localname" ]

                      then

                        mvdir=$outdir/$testerZ/$(basename "$localname");

                        if [ -e $mvdir ]

                        then

                            if [ $mvdir -nt "$localname" ]

                            then

      if [ $verbose ]

      then

      echo "$mvdir is newer than $localname, so I am going to cp $mvdir to $localname."

                    echo "Removing ${localname}.old}"

      fi

      rm -f "${localname}.old"

      if [ $verbose ]

      then

      echo "Done."

      echo "Moving $localname to ${localname}.old for a backup."

                    fi

      mv "$localname" "${localname}.old"

                    if [ $verbose ]

      then

      echo "Done."

      echo "Copying $mvdir to $localname, preserving permissions."

      fi

      cp -p "$mvdir" "$localname"

      if [ $verbose ]

      then

      echo "Done."

                            fi

      elif [ $mvdir -ot "$localname" ]

      then

      if [ $verbose ]

      then

      echo "$localname is newer than $mvdir, so I am going to cp $localname to $mvdir."

                    echo "Removing ${mvdir}.old"

      fi

      rm -f "${mvdir}.old"

      if [ $verbose ]

      then

      echo "Done."

      echo "Moving $mvdir to ${mvdir}.old for a backup."

                    fi

      mv "$mvdir" "${mvdir}.old"

      if [ $verbose ]

      then

      echo "Done"

      echo "Copying $localname to $mvdir"

                    fi

      cp -p "$localname" "$mvdir"

      if [ $verbose ]

      then

      echo "Done"

      fi

      else

      if [ $verbose ]

      then

      echo "These two files are the same age, so I will do nothing."

                            fi

      fi

                        else

      if [ $verbose ]

      then

      echo "$mvdir does not exist, so I'll just copy $usbname to $mvdir"

                            fi

      cp -p "$localname" "$mvdir"

                            if [ $verbose ]

      then

      echo "Done"

      fi

  fi 

                    fi

      else

        if [ $verbose ]

        then

        echo "$localname ended in .old, so I skipped it. Duh. Don't want to have a bunch of *.old.old.old files hanging around."

        fi

      fi

                    done

     

    fi

    fi

    cd $indir

  let "index = $index + 1"

 

done

IFS=$old_IFS

 

Is there a better or more correct way of doing this?

Edited by Steve Scrimpshire
Link to comment
Share on other sites

Thanks, Yves. It actually works out for me this way, because I've been playing around with it and I have made it so that if you don't have those two options, it asks you to enter them at the cli. (I even made it so that if one of the directories doesn't exist, it'll ask if you want to create it.)

Link to comment
Share on other sites

You're welcome! I didn't help in any way, as you've already got things rights :)

 

BTW, be carefull of statements like that: if [ -z $indir -o -z $outdir ]. You should use a lot more quotes, because if indir or outdir indeed IS empty, bash will either complain, or not work as expected, since $indir or $outdir is replaced by nothing...

 

Yves.

Link to comment
Share on other sites

Thanks again. I usually quote everything, even when I don't have to. Got sloppy with this one, because it was making me angry.

 

Merci encore, mon ami.

(I remember a little French...lol...Je parles francais un peu. Probably poor grammar and I know I'm missing French characters.)

Link to comment
Share on other sites

Me too :lol:

When I program a main code, inside of which a private function is called, I often don't even trust the main code from inside the function, for giving parameters as they should be; I often simply take every case into account... I must be mad.

 

Yves

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...