LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 02-20-2009, 04:19 PM   #1
Mogget
Member
 
Registered: Dec 2008
Location: Norway
Distribution: Debian
Posts: 43

Rep: Reputation: 15
How to get "case" to overwrite preset variables in a bash script


Problem description: I'm making a backup script for bash that will run without options in the command line. It's then suppose to use the preset variables in the script. I also want to be able to input options that will be used instead of the preset variables.

The problem is that the way I'm doing it doesn't work properly, the preset variables doesn't get overwritten with the values i put in at the command line. Does anyone have an idea what I'm doing wrong or suggestions for better ways to do this?

Thank you in advance for taking the time to look at this and help out.

Code:
#!/bin/bash

# Basic backup script to test how to get case working like i want it to.

###################################################################################################
###################################################################################################

# Variables that the script uses if no options are used when starting program.

DDIR=/tmp			# full path to mounted backup drive including sub folders for user
DATE=`date +"%d%m%y"`		# Outputs todays date in this form --> ddmyy

###################################################################################################
###################################################################################################

# Backup script.

while test $# -ge 1
do
  case "$1" in
	  -h* | --help)
		echo 'usage:'
		echo '	'$0' [ (-dd) --dest_dir=DESTINATION DIRECTORY]'
		echo '       [ (-hd) --home_dir=HOME DIRECTORY]'
		exit 0;;
	  -dd=* | --dest_dir=*) DDIR=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
	  -hd=* | --home_dir=*) HOME=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
			     *) echo "unknown option: $1"; echo "$0 --help for help"; exit 1;;
  esac
done

# Checking if $HOME and $DDIR has the right permissions and if $USER.$DATE.cpio allready exist or not.
# If permissions are correct and $USER.$DATE.cpio does not exist we will make a backup of $HOME

if [ -r $HOME ]; then
  if [ -w $DDIR ]; then
    if [ -f $DDIR/$USER.$DATE.cpio ]; then
      echo "Backup has allready been done, exiting now."
      exit 0
    else
      cd $HOME
      find . -print | cpio --create --format=crc > $DDIR/$USER.$DATE.cpio
    fi
  else
    echo "$DDIR is not writeable, exiting now."
    exit 0
  fi
else
  echo "$HOME is not readable, exiting now."
  exit 0
fi

echo "Backup of $HOME has been stored as $DDIR/$USER.$DATE.cpio."
exit 0
$HOME and $USER are already defined in bash for me, how and why I don't know. But that's why I'm using them without defining them in the script.
 
Old 02-20-2009, 04:33 PM   #2
TheLinuxDuck
Member
 
Registered: Sep 2002
Location: Tulsa, OK
Distribution: Slack, baby!
Posts: 349

Rep: Reputation: 33
Seems to work fine for me:

Code:
#!/bin/bash

DDIR=/tmp               # full path to mounted backup drive including sub folders for user
DATE=`date +"%d%m%y"`   # Outputs todays date in this form --> ddmyy

while test $# -ge 1
do
  case "$1" in
    -h* | --help)
      echo 'usage:'
      echo '  '$0' [ (-dd) --dest_dir=DESTINATION DIRECTORY]'
      echo '       [ (-hd) --home_dir=HOME DIRECTORY]'
      exit 0;;
    -dd=* | --dest_dir=*) DDIR=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
    -hd=* | --home_dir=*) HOME=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
    *) echo "unknown option: $1"; echo "$0 --help for help"; exit 1;;
  esac
done

echo "DDIR $DDIR"
echo "HOME $HOME"

Code:
~> ./testvars.sh -dd=/tmp/tmp
DDIR /tmp/tmp
HOME /root
~> ./testvars.sh --dest_dir=/tmp/tmp
DDIR /tmp/tmp
HOME /root
Fri Feb 20 16:31:34 CST 2009 root
~> ./testvars.sh --home_dir=/tmp/tmp
DDIR /tmp
HOME /tmp/tmp
 
Old 02-20-2009, 05:22 PM   #3
Mogget
Member
 
Registered: Dec 2008
Location: Norway
Distribution: Debian
Posts: 43

Original Poster
Rep: Reputation: 15
Thank you for testing that for me.

While I was waiting for an answer I think I found the solution to my problem.
In my original script i have several variables that depend on one variable so when i update the value of one, i need to update all the others that has used that variable?

Meaning if I do this

Code:
VAR1=/tmp
VAR2=$VAR1/$USER

while test $# -ge 1
do
  case "$1" in
        -dd=* | --dest_dir=* ) VAR1=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
                           * ) echo "something something"; exit 1;;
  esac
done

echo "$VAR1 and $VAR2"
The output of $VAR2 would be the same with or without the -dd= option at the command line.
So in order for this to work i would have to exchange this

Code:
-dd=* | --dest_dir=* ) VAR1=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
for this
Code:
-dd=* | --dest_dir=* ) VAR1=`echo $1 | sed 's/[-a-z_]*=//'`; VAR2=$VAR1/$USER; shift;;
I'm very sorry for wasting your time, been sitting here for so long that i didn't see that.
 
Old 02-21-2009, 12:42 PM   #4
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Hello Mogget

Glad you got it sorted.

You might like to look at getopts for parsing the command line -- it's easier than using homegrown code, more transparent to read (and hence maintain) and runs quicker than subshell spawning echos and seds (not that they're a big deal).

That said, your programming style is nice -- very easy to read and understand.

Here's a sample getopts usage, from a backup script. The usage function is listed first to show what the getopts code is implementing
Code:
#--------------------------
# Name: usage
# Purpose: prints usage message
#--------------------------
function usage {

    echo "usage: $prgnam -c <cfg file> [-d] [-h] [-l <log dir>] [-s DVD_write | DVD_verify]" >&2
    if [[ ${1:-} = '' ]]
    then
        echo "(use -h for help)" >&2
    else
        echo "where:
    -c names the configuration file.  If it does not begin with / then it is prefixed with $cfg_dir
       See sample configuration file for more information.
    -d turns debugging trace on
    -h prints this help
    -l names the log directory, default $log_dir
    -s skips to DVD write (DVD_write) or verification (DVD_verify).  Intended for use after either has failed.
" >&2
    fi

}  # end of function usage

    # Set defaults
    # ~~~~~~~~~~~~
    cfg_dir="/etc/opt/$prgnam/"         # can only be overridden on the command line
    log_dir="/var/opt/$prgnam/log/"     # can only be overridden on the command line
    DVD_mnt_dir="/var/tmp/$prgnam/mnt/DVD/"
    skip_to=''
    snapshot_mnt_base_dir="/var/tmp/$prgnam/mnt/snapshots/"

    # Parse command line
    # ~~~~~~~~~~~~~~~~~~
    args="${*:-}"
    while getopts c:dhl:s: opt 2>/dev/null
    do
        case $opt in
            c)
                if [[ ${OPTARG:0:1} != '/' ]]; then
                    cfg_afn="${cfg_dir}$OPTARG"
                else
                    cfg_afn="$OPTARG"
                fi
                ;;
            d )
                debug='YES'
                ;;
            h )
                usage -v
                \exit 0
                ;;
            l)
                if [[ ${OPTARG:0:1} != '/' ]]; then
                    usage -v
                    \exit 0
                fi
                log_dir="$OPTARG"
                if [[ ${log_dir:${#log_dir}} != '/' ]]; then
                    log_dir="$log_dir/"
                fi
                ;;
            s )
                case "$OPTARG" in
                    'DVD_write' | 'DVD_verify' )
                        skip_to="$OPTARG"
                        ;;
                    * )
                        echo "Option -s: invalid value '$OPTARG'" >&2
                        usage
                        \exit 1
                        ;;
                esac
                ;;
            * )
                usage
                \exit 1
        esac
    done

    # Test for extra arguments
    # ~~~~~~~~~~~~~~~~~~~~~~~~
    shift $(( $OPTIND-1 ))
    if [[ $* != '' ]]; then
        usage
        \exit 1
    fi

    # Test for any mandatory options not set
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if [[ ${cfg_afn:-} = '' ]]; then
        usage
        \exit 1
    fi
Best

Charles
 
Old 02-24-2009, 01:19 PM   #5
Mogget
Member
 
Registered: Dec 2008
Location: Norway
Distribution: Debian
Posts: 43

Original Poster
Rep: Reputation: 15
Thank you very much for the compliment. I will have to look into this as soon as im done with the code i'm working on now.
The code seems a little bit over my head, but i think i will understand it after some reading, thinking and maybe some skimming of man files.

Again thank you for giving me some feedback. I have been working alot on this lately and i think i soon have a script that is pretty versatile no matter the machine.
 
  


Reply

Tags
backup, bash, case



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
bash script: using "select" to show multi-word options? (like "option 1"/"o zidane_tribal Programming 7 12-19-2015 01:03 AM
bash: "cut" and "case" help please tredegar Linux - Newbie 14 06-26-2008 04:31 PM
Bash: How to setup "global" environment variables? ArthurHuang Programming 2 02-07-2008 12:24 PM
How to write a bash script to replace all "KH" to "K" in file ABC??? cqmyg5 Slackware 4 07-24-2007 09:00 AM
Pattern matching with a "case" statement in BASH King V Programming 8 04-27-2006 04:19 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:34 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration