Как изменить каталог в конце скрипта bash?

В моих .bashrc:

function rnew { $HOME/.dotfiles/railsnewapp.sh $1; }

По сути, я вызываю rnew из любого каталога, и он создает каталог в ~/code/appname, устанавливает в него Rails, а затем я хочу [ 115] стать ~/code/appname.

В ~/.dotfiles/railsnewapp.sh:

#! /bin/bash
appname=$1
appdirectory="$HOME/code/$appname"
if [ -d $appdirectory ]; then
  echo $appdirectory already exists. Not creating Rails app $appname.
else
  mkdir $appdirectory
  cd $appdirectory
  if [ `pwd` == $appdirectory ]; then
    echo "rvm use 1.8.7@$appname" >> "$appdirectory/.rvmrc"
    rvm gemset create $appname
    cd ..
    rails new $appname -m $HOME/code/config/base_template.rb -T -J
    cd $appdirectory
    if [ `pwd` == $appdirectory ]; then
      git init .
    else
      echo Could not create git repo in $appdirectory. Could not switch to that directory.
    fi

  else
    echo Could not switch to directory $appdirectory. No creating Rails app $appname.
  fi
fi

######## how to switch to $appdirectory here so that 
######## when the `rnew` function completes and I'm back at the
######## terminal and the `pwd` is $appdirectory?

Ps. Я не хочу делать cd в rnew. Как вы можете видеть из сценария, я проверяю, что приложение создано в правильном каталоге и других проверках, связанных с каталогом, поэтому я не думаю, что могу вызвать сценарий из rnew для каталога, который еще не быть создан?

0
задан 29 April 2011 в 21:54

3 ответа

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

function rnew { . $HOME/.dotfiles/railsnewapp.sh $1; }

Это встроенная оболочка, из [ 114]:

.: . filename [arguments]
    Execute commands from a file in the current shell.

    Read and execute commands from FILENAME in the current shell.  The
    entries in $PATH are used to find the directory containing FILENAME.
    If any ARGUMENTS are supplied, they become the positional parameters
    when FILENAME is executed.

    Exit Status:
    Returns the status of the last command executed in FILENAME; fails if
    FILENAME cannot be read.

Обратите внимание, что это делает сценарий railsnewapp.sh выполненным в текущей оболочке, переменные, определенные в сценарии оболочки, будут доступны оболочке после ее завершения.

0
ответ дан 29 April 2011 в 21:54

Почему бы просто не сделать все это в этой функции? Что-то вроде:

rnew() {
    local appdir="$HOME/code/$1"
    mkdir "$appdir" || return
    echo "rvm use 1.8.7@$1" > "$appdir/.rvmrc"
    (cd "$appdir" && rvm gemset create "$1") || return
    rails new "$1" -m "$HOME/code/config/base_template.rb" -T -J || return
    cd "$appdir" && git init .
}
0
ответ дан 29 April 2011 в 21:54

Другой вариант: ваш скрипт напечатает имя каталога в конце скрипта.

...
echo "$appdirectory"
exit

При любых условиях ошибки выведите сообщение об ошибке в stderr (echo something >&2) и выйдите с ненулевым кодом возврата (exit 1). В любом случае, это хорошая практика.

Тогда функция может выглядеть так:

rnew () { 
    local dir=$( $HOME/.dotfiles/railsnewapp.sh "$1" )
    [[ $? -eq 0 ]] && cd "$dir" 
}
0
ответ дан 29 April 2011 в 21:54

Другие вопросы по тегам:

Похожие вопросы: