无法在当前环境中多次运行BASH脚本

发布于 2024-11-19 19:42:53 字数 1465 浏览 2 评论 0原文

我有一个 bash 脚本,用于从当前所在的任何位置从源目录移动到 bin 目录(我将此脚本称为“传送”)。因为它基本上只是一个美化的“cd”命令,所以我必须在当前 shell 中运行它(即 . ./teleport.sh )。我在 .bashrc 文件中设置了一个别名,以便“teleport”与“.bashrc”匹配。传送.sh'。

我第一次运行它,效果很好。但是,如果我在运行一次后再次运行它,它不会执行任何操作。如果我关闭终端然后打开一个新终端,它会再次工作,但只是第一次。我的直觉是 BASH 内部发生了一些我不熟悉的事情,所以我想我应该通过这里的专家来运行它,看看是否能得到答案。

该脚本是:

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

我对它的用法是这样的:

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$

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$

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

只为守护你 2024-11-26 19:42:53

问题是 getopts 必须保留一点状态,以便可以在循环中调用它,并且您没有清除该状态。每次调用它时,它都会再处理一个参数,并递增 shell 的 OPTIND 变量,以便它知道下次调用时要处理哪个参数。当它处理完所有参数后,每次调用它都会返回 1 (false),这使得 while 退出。

第一次获取脚本时,它会按预期工作。第二次(以及第三次、第四次...)时,getopts 除了返回 false 之外什么也不做。

在开始循环之前添加一行以重置状态:(

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

我假设您的记录中存在拼写错误,因为它显示您在第二次尝试时调用脚本 - 而不是获取它,但这不是这里真正的问题。)

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.)

划一舟意中人 2024-11-26 19:42:53

问题是,第一次调用时,您正在获取脚本(这就是“../teleport”)所做的事情,该脚本在当前 shell 中运行脚本,从而保留 cd。第二次调用它时,它没有来源,因此您创建一个子 shell,cd 到适当的目录,然后退出子 shell,让您回到调用脚本的位置!

实现此功能的方法很简单,就是在当前 shell 中(即在脚本外部)创建 teleportToSrc 和 teleportToObj 别名或函数

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)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文