开发者

Unable to run BASH script in current environment multiple times

开发者 https://www.devze.com 2023-03-20 07:47 出处:网络
I have a bash script that I use to move from source to bin directories from anywhere I currently am (I call this script, \'teleport\'). Since it basically is just a glorified \'cd\' command, I have to

I have a bash script that I use to move from source to bin directories from anywhere I currently am (I call this script, 'teleport'). Since it basically is just a glorified 'cd' command, I have to run it in the current shell (i.e. . ./teleport.sh ). I've set up an alias in my .bashrc file so that 'teleport' matches '. teleport.sh'.

The first time I run it, it works fine. But then, if I run it again after it has run once, it doesn't do anything. It works again if I close my terminal and then open a new one, but only the first time. My intuition is that there is something internally going on with BASH that I'm not familiar with, so I thought I would run it through the gurus here to see if I can get an answer.

The script is:

numargs=$#

function printUsage 
{
        echo -e "Usage: $0 [-o | -s] <PROJECT>\n"
        echo -e "\tMagically teleports you into the main source directory of a project.\n"
        echo -e "\t PROJECT: The current project you wish to teleport into."
        echo -e "\t -o: Teleport into the objdir.\n"
        echo -e "\t -s: Teleport into the source dir.\n"
}

if [ $numargs -lt 2 ]
then
        printUsage
fi

function teleportToObj
{
  OBJDIR=${HOME}/Source/${PROJECT}/obj
  cd ${OBJDIR}
}

function teleportToSrc
{
  cd ${HOME}/Source/${PROJECT}/src
}

while getopts "o:s:" opt
do
  case $opt in
    o)
      PROJECT=$OPTARG
      teleportToObj
      ;;
    s)
      PROJECT=$OPTARG
      teleportToSrc
      ;;
   esac
done

My usage of it is something like:

sjohnson@corellia:~$ cd /usr/local/src
sjohnson@corellia:/usr/local/src$ . ./teleport -s some-proj
sjohnson@corellia:~/Source/some-proj/src$ teleport -o some-proj
sjohnson@corellia:~/Source/some-proj/src$ 
<... START NEW TERMINAL ...>
sjohnson@corellia:~$ . ./teleport -o some-proj
sjohnson@corellia:开发者_如何转开发~/Source/some-proj/obj$


The problem is that getopts necessarily keeps a little bit of state so that it can be called in a loop, and you're not clearing that state. Each time it's called, it processes one more argument, and it increments the shell's OPTIND variable so it'll know which argument to process the next time it's called. When it's done with all the arguments, it returns 1 (false) every time it's invoked, which makes the while exit.

The first time you source your script, it works as expected. The second (and third, fourth...) time, getopts does nothing but return false.

Add one line to reset the state before you start looping:

unset OPTIND   # clear state so getopts will start over
while getopts "o:s:" opt
do
    # ...
done

(I assume there's a typo in your transcript, since it shows you invoking the script -- not sourcing it -- on the second try, but that's not the real problem here.)


The problem is that the first time you call is you are sourcing the script (thats what ". ./teleport") does which runs the script in the current shell thus preserving the cd. The second time you call it, it isn't sourced so you create a subshell, cd to the appropriate directory, and then exit the subshell putting you right back where you called the script from!

The way to make this work is simply to make teleportToSrc and teleportToObj aliases or functions in the current shell (i.e. outside a script)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号