Find the answer to your Linux question:
Results 1 to 9 of 9
Hi, I want to be able to use getopts so that I can emulate "rm" by creating a script and making it an alias called "rm" I want to do ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Jul 2006
    Posts
    5

    Using getopts


    Hi,

    I want to be able to use getopts so that I can emulate "rm" by creating a script and making it an alias called "rm" I want to do it so that I dont actually I delete anything, instead I copy the files to a specified folder. So far my script looks like this :

    Code:
    #!/bin/bash
    
    
    function moveFiles () {
    
    mv -f $OPTARG $GARBAGE
    }
    
    
    mkdir $HOME/deleted/
    GARBAGE=$HOME/deleted/
    NO_ARGS=0
    SEPLIST="/t"
    
    
    if [ $# -eq "$NO_ARGS" ]
    then
      echo "rm: too few arguments"
      echo "Try \`rm --help\` for more information"
    fi
    
    while getopts :r:R:f:v:i option; do
        case $option in
            r)  SEPLIST=$OPTARG
                moveFiles
            ;;
            R)
                SEPLIST=$OPTARG
                moveFiles
            ;;
            f)
                echo "testing"
            ;;
            v)
                echo "testing"
            ;;
            i)
                echo "testing"
            ;;
            [?])
                echo  "invalid option -- $option"
                echo  "try \`rm --help\` for more information"
            ;;
      esac
    done
    as you can see, I have still along way to go but I have been testing the getopts command and when I enter options followed by a file name I get errors, but if I select one option it processos fine, can anyone explain a little more about getopts for me? I want to set precedence between options too but cant find any help on where to do this.

    Jack

  2. #2
    Linux Newbie birdman's Avatar
    Join Date
    Mar 2006
    Location
    Ireland
    Posts
    141
    I believe the problem may be in the way you are testing. As far as I know a colon after an option in the options argument indicates that the option will have an argument ($OPTARG accesses it i think). If you remove the colons I have a feeling your test will work, but I don't know if that is what you want to do.

  3. #3
    Linux User
    Join Date
    Jun 2006
    Posts
    311
    Hi jack1981,
    birdman is right. Change this line in your script
    while getopts :r:R:f:v:i option; do
    to this one.
    while getopts rRfvi option; do
    can anyone explain a little more about getopts for me?
    Read these : -

    http://www.mkssoftware.com/docs/man1/getopts.1.asp

    http://www.opengroup.org/onlinepubs/...s/getopts.html

    With Regards,
    Thinker

  4. #4
    Just Joined!
    Join Date
    Jul 2006
    Posts
    5
    Hi again, I finally got getopts to work okay, thanks for the advice, my script functions about 80% like command rm. What I could do with knowing now is how do I get rid of that code at the bottom and provide maybe a function to perform the check, I need to be able to give the last option precedence if it contradcits another option when multiple options are specified.

    Here is my script so far:

    Code:
    #!bin/bash
    # program to emulate the "rm" command in UNIX.
    
    
    #  CREATE TRASH FOLDER
    
    if ! [ -d "$HOME/deleted" ] ; then
         mkdir $HOME/deleted
    fi
    
    # INITIALIZE VARIABLES
    
    NO_ARGS=0
    FLAG_R=0
    FLAG_F=0
    FLAG_I=0
    FLAG_V=0
    TRASH=$HOME/deleted
    
    
    # FUNCTIONS
    
    function errorInvalidOpt() {
    
        echo "rm: invalid option - $o"
        echo "try \`rm -help\` for more information"
        exit 0
    }
    
    
    function errorTooFew() {
    
       echo "rm: too few arguments"
       echo "try \`rm --help\` for more information"
    }
    
    function errorNoSuch() {
    
       echo "rm: cannot remove $* : no such file or directory"
    }
    
    function okDelete() {
    
    echo -n "rm: remove $* ?"
        read ANSWER
        if [ "$ANSWER" = "y" ] ; then
        mv $@ $TRASH
    fi
    }
    
    function notifyDelete() {
    
    if  [ -f  ] ; then
       echo "removing \`$*'"
       mv $@ $TRASH
    
    fi
    }
    
    function  okNotify() {
    
    echo -n "rm: remove $* ?"
        read ANSWER
        if [ "$ANSWER" = "y" ] ; then
        notifyDelete $@
    
    fi
    }
    
    function delete() {
       if ! [ -f ] ; then
       errorNoSuch;
       else
       mv  $@ $TRASH
    fi
    }
    
    
    # GETOPTS
    
    while getopts :rRfvi o
    do    case $o in
    
               r|R) FLAG_R=1 ;;
                 f) FLAG_F=1 ;;
                 v) FLAG_V=1 ;;
                 i) FLAG_I=1 ;;
                 *) errorInvalidOpt
    
          esac
    done
    shift `expr $OPTIND - 1`
    
    # FLOW CONTROL
    
    if [ "$#" -eq "$NO_ARGS" ] ; then
       errorTooFew
    
    elif [ $FLAG_R -eq  0 ] && [ $FLAG_F -eq 0 ] && [ $FLAG_I -eq 0 ] && [ $FLAG_V -eq 0 ] ; then
       delete $@
    
    elif [ $FLAG_R -eq  1 ] && [ $FLAG_F -eq 1 ] && [ $FLAG_I -eq 1 ] && [ $FLAG_V -eq 1 ] ; then
       okNotify $@
    
    elif [ $FLAG_R -eq  1 ] && [ $FLAG_F -eq 1 ] && [ $FLAG_I -eq 1 ] ; then
       okNotify $@
    
    elif [ $FLAG_F -eq 1 ] && [ $FLAG_I -eq 1 ] && [ $FLAG_V -eq 1 ] ; then
       okNotify $@
    
    elif [ $FLAG_R -eq  1 ] && [ $FLAG_I -eq 1 ] && [ $FLAG_V -eq 1 ] ; then
       okNotify $@
    
    elif [ $FLAG_R -eq  1 ] && [ $FLAG_V -eq 1 ] ; then
       notifyDelete $@
    
    elif [ $FLAG_V -eq 1 ] && [ $FLAG_I -eq 1 ] ; then
       okNotify $@
    
    elif [ $FLAG_F -eq 1 ] && [ $FLAG_I -eq 1 ] ; then
       notifyDelete $@
    
    elif [ $FLAG_R -eq 1 ] ; then
       delete $@
    
    elif [ $FLAG_V -eq 1 ] ; then
       notifyDelete $@
    
    elif [ $FLAG_I -eq 1 ] ; then
       okDelete $@
    
    elif [ $FLAG_F -eq 1 ] ; then
       delete $@
    fi
    So really I need to create a function to check which flags have been activated and then process the argument accordingly, any help or advice would be great.

    Thanks for other posts!

    Mike

  5. #5
    Linux User
    Join Date
    Jun 2006
    Posts
    311
    Hi jack1981,
    # FLOW CONTROL

    if [ "$#" -eq "$NO_ARGS" ] ; then
    errorTooFew

    elif [ $FLAG_R -eq 0 ] && [ $FLAG_F -eq 0 ] && [ $FLAG_I -eq 0 ] && [ $FLAG_V -eq 0 ] ; then
    delete $@
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    One suggestion that I have for reducing the usage of elif and checking of all your variable values is to combine your four variables FLAG_R, FLAG_F, FLAG_V and FLAG_I into a single variable and then use a case statement to handle the options.

    With Regards,
    Thinker

  6. #6
    Just Joined!
    Join Date
    Jul 2006
    Posts
    5
    Quote Originally Posted by Thinker
    Hi jack1981,

    One suggestion that I have for reducing the usage of elif and checking of all your variable values is to combine your four variables FLAG_R, FLAG_F, FLAG_V and FLAG_I into a single variable and then use a case statement to handle the options.

    With Regards,
    Thinker
    Cheers for the reply Thinker, even if I assign them all to a variable like so:

    OPTS=$FLAG_R$FLAG_V$FLAG_I$FLAG_F
    echo $OPTS
    0000

    I am still left with a list of numbers which have many different possible
    combinations and my case would still have to allow for these and would probably be quite long in the end.

    Either that or I miss understand you, what do you reckon?

    Thanks again

    Jack

  7. #7
    Linux User
    Join Date
    Jun 2006
    Posts
    311
    Hi jack1981,
    Since there are only four variables and two values possible ( 0 or a 1 ), 16 combinations are possible.

    But you can use wildcards like '?' with case statement, so that you can cover all combinations in lesser lines and this section of script would look more readable.

    With Regards,
    Thinker

  8. #8
    Just Joined!
    Join Date
    Jul 2006
    Posts
    5
    Quote Originally Posted by Thinker
    Hi jack1981,
    Since there are only four variables and two values possible ( 0 or a 1 ), 16 combinations are possible.

    But you can use wildcards like '?' with case statement, so that you can cover all combinations in lesser lines and this section of script would look more readable.

    With Regards,
    Thinker
    Hi Thinker,

    your first post got me thinking a little, I then changed my flag values to resemble proper options after also noticing the options for "mv" and "rm" are very similar to each other. I then came up with this:

    Code:
    #!/bin/bash
    # program to emulate the "rm" command in UNIX.
    
    
    #  CREATE TRASH FOLDER
    
    if ! [ -d "$HOME/deleted" ] ; then
         mkdir $HOME/deleted
    fi
    
    # INITIALIZE VARIABLES
    
    NO_ARGS=0
    FLAG_R=""
    FLAG_F=""
    FLAG_I=""
    FLAG_V=""
    TRASH=$HOME/deleted
    
    
    # FUNCTIONS
    
    function errorInvalidOpt() {
    
        echo "rm: invalid option - $o"
        echo "try \`rm -help\` for more information"
        exit 0
    }
    
    
    function errorTooFew() {
    
       echo "rm: too few arguments"
       echo "try \`rm --help\` for more information"
    }
    
    function errorNoSuch() {
    
       echo "rm: cannot remove $* : no such file or directory"
    }
    
    
    function writePro () {
    echo -n "rm: remove write-protected file \`$*'?"
    read ANSWER
        if [ "$ANSWER" = "y" ] ; then
        delete
    fi
    }
    
    function delete() {
       if [ "$FLAG_I" = "i" ]; then
       echo -n "rm: remove $* ?"
       read ANSWER
       elif [ "$ANSWER" = "y" ] ; then
       mv $OPTS$@$TRASH 2>/dev/null
       elif [ "$FLAG_V" = "v" ] ; then
       mv $OPTS$@$TRASH 2>/dev/null
       echo "removing \`$*'"
       else
       mv $OPTS$@$TRASH 2>/dev/null
    fi
    }
    
    
    # GETOPTS
    
    while getopts :rRfvi o
    do    case $o in
    
               R|r) FLAG_R=""
                  ;;
                 f) FLAG_F=f
                  OPT=-
                  ;;
                 v) FLAG_V=v
                 OPT=- 
                 ;;
                 i) FLAG_I=i
                 OPT=i
                  ;;
                 *) errorInvalidOpt
    
          esac
    done
    shift `expr $OPTIND - 1`
    
    # FLOW CONTROL
    OPT=-
    OPTS=$OPT$FLAG_R$FLAG_F$FLAG_I$FLAG_V
    
    if [ "$#" -eq "$NO_ARGS" ] ; then
       errorTooFew
    elif ! [ -f "$1" ] ; then
    errorNoSuch
    else
     delete $@
    fi
    which is pretty close to complete, bar the precedence, I need to give the last option precedence where there is a contradiction.

    Any ideas?

    thanks again

    Jack

  9. #9
    Just Joined!
    Join Date
    Jul 2006
    Posts
    5
    Hi,

    I got it working! finally..

    heres what I did in the end:

    Code:
    #!/bin/bash
    # program to emulate the "rm" command in UNIX.
    # less the endless sp
    
    #  CREATE TRASH FOLDER
    
    if ! [ -d "$HOME/deleted" ] ; then
         mkdir $HOME/deleted
    fi
    
    # INITIALIZE VARIABLES
    OPT=-
    NO_ARGS=0
    FLAG_R=""
    FLAG_F=""
    FLAG_I=""
    FLAG_V=""
    TRASH=$HOME/deleted
    
    
    # FUNCTIONS
    
    function errorInvailidOpt() {
    
        echo "rm: invalid option - $o"
        echo "try \`rm -help\` for more information"
        exit 0
    }
    
    
    function errorTooFew() {
    
       echo "rm: too few arguments"
       echo "try \`rm --help\` for more information"
    }
    
    function errorNoSuch() {
    
       echo "rm: cannot remove $* : no such file or directory"
    }
    
    
    function writePro () {
    echo -n "rm: remove write-protected file \`$*'?"
    read ANSWER
        if [ "$ANSWER" = "y" ] &&  [ "$FLAG_V" = "v" ] ; then
        mv $OPTS $@ $TRASH 2>/dev/null
        echo "removing \`$*'"
        else
        mv $OPTS $@ $TRASH 2>/dev/null
    
    fi
    }
    
    function verbose () {
    mv $@ $TRASH 2>/dev/null
    echo "removing \`$*'"
    }
    function intVerbose () {
    echo -n "rm: remove $* ?"
        read ANSWER
        if [ "$ANSWER" = "y" ] ; then
        mv  $@ $TRASH 2>/dev/null
        echo "removing \`$*'"
    
    
    fi
    }
    
    function int () {
    echo -n "rm: remove $* ?"
        read ANSWER
        if [ "$ANSWER" = "y" ] ; then
        mv  $@ $TRASH 2>/dev/null
    fi
    }
    
    function delete() {
    while :
    do  case $OPTS in
    
          v|ivf|vf|ifv|vif) verbose $@
                          break
                          ;;
         vfi|fvi|iv|vi|fiv) intVerbose $@
                          break
                          ;;
                   f|fv|if) mv -f $@ $TRASH 2>/dev/null
                          break
                          ;;
                         i) int $@
                          break
                          ;;
                         r)mv $OPTS $@ $TRASH 2>/dev/null
                          break
                          ;;
                         *)mv $@ $TRASH 2>/dev/null
                          break
    
    esac
    done
    
    }
    
    
    # GETOPTS
    
    while getopts :rRfvi o
    do    case $o in
               r|R)FLAG_R=""
                 ;;
                 f) FLAG_F=f
                 ;;
                 v) FLAG_V=v
                 ;;
                 i) FLAG_I=i
                 ;;
                 *) errorInvalidOpt
    
          esac
    done
    shift `expr $OPTIND - 1`
    
    # FLOW CONTROL
    
    OPTS=$FLAG_R$FLAG_F$FLAG_I$FLAG_V
    
    if [ "$#" -eq "$NO_ARGS" ] ; then
       errorTooFew $@
    elif ! [ -f  "$1" ] &&  ! [ -d "$1" ]; then
       errorNoSuch $@
    elif ! [ -w  "$1" ] ; then
       writePro $@
    else
       delete $@
    fi

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •