Невозможно запустить BASH-скрипт в текущей среде несколько раз - PullRequest
2 голосов
/ 14 июля 2011

У меня есть скрипт bash, который я использую для перемещения из исходных каталогов в каталог bin из любого места, где я сейчас нахожусь (этот скрипт я называю «телепорт»). Так как это в основном просто прославленная команда 'cd', я должен запустить ее в текущей оболочке (то есть ./teleport.sh). Я установил псевдоним в своем файле .bashrc, чтобы «телепорт» соответствовал ». teleport.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$

Ответы [ 2 ]

5 голосов
/ 14 июля 2011

Проблема в том, что getopts обязательно сохраняет немного состояния, чтобы его можно было вызывать в цикле, и вы не очищаете это состояние. Каждый раз, когда он вызывается, он обрабатывает еще один аргумент и увеличивает переменную оболочки OPTIND, чтобы он знал, какой аргумент обрабатывать при следующем вызове. Когда это сделано со всеми аргументами, он возвращает 1 (false) каждый раз, когда вызывается, что приводит к выходу while.

При первом запуске сценария он работает как положено. Второй (и третий, четвертый ...) раз, getopts ничего не делает, кроме как возвращает ложь.

Добавьте одну строку для сброса состояния перед началом цикла:

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

(Полагаю, в вашей расшифровке есть опечатка, поскольку она показывает, что вы вызываете скрипт, а не извлекаете его со второй попытки, но здесь проблема не в этом.)

2 голосов
/ 14 июля 2011

Проблема в том, что при первом вызове вы выбираете сценарий (вот что делает "./teleport"), который запускает сценарий в текущей оболочке, сохраняя при этом компакт-диск.Во второй раз, когда вы вызываете его, он не получен, поэтому вы создаете подоболочку, перейдите в соответствующий каталог и затем выходите из подоболочки, возвращая вас туда, откуда вы вызвали скрипт!

Способ созданияэта работа заключается в том, чтобы просто создать псевдонимы или функции teleportToSrc и teleportToObj в текущей оболочке (т.е. вне скрипта)

...