2016-04-03 6 views
1

Я работаю над проектом для удаленного создания репозитория в моем экземпляре GitLab CE (эта часть работает!), А затем для создания каталога с именем проект (рабочий!) и cd в этот каталог (вот где у меня проблема ...), а затем инициализировать локально и добавить удаленный репозиторий (работает !!!)скрипт bash для создания и cd в каталог с пробелами в имени

Проблема, которую я имею, меняет в новый каталог. Использую ли я код, показанный ниже, или просто попробую cd "$1" или cd "$*" Я не могу заставить его работать вообще!

#!/bin/bash 

dir="$*" 
wd=$(pwd) 
fulldir="$(pwd)/${dir// /\\ }/" 
echo "Creating directory $dir" 
mkdir -v "$dir" 
cd "$dir" 
echo "Changing current directory to $dir" 
echo $dir 
echo $fulldir 

Выход этого кода:

[email protected]:~# ls 
glnewproj test 
[email protected]:~# bash test Hello World 
Creating directory Hello World 
mkdir: created directory 'Hello World' 
Changing current directory to Hello World 
Hello World 
/root/Hello\ World/ 
[email protected]:~# ls 
Hello World glnewproj test 
[email protected]:~# pwd 
/root 

Как я могу cd в моей вновь созданный каталог? Я полностью в тупике.

Edit:

отпечатал функцию за Ghoti и протестировали его в .bashrc и в моем тестовом скрипте.

При выполнении функции непосредственно из Баш:

[email protected]:~# ls 
glnewproj test test2 
[email protected]:~# mkcd "Hello World" 
[email protected]:~/Hello World# 

При выполнении функции внутри нового тестового сценария:

[email protected]:~# ls 
glnewproj test test2 
[email protected]:~# cat test2 
#!/bin/bash 

mkcd() { 
    mkdir -p "$1" && cd "$1" 
} 

mkcd "$1" 

[email protected]:~# bash test2 "Hello World" 
[email protected]:~# ls 
Hello World glnewproj test test2 

Так что сценарий все еще работает как ребенок, и, таким образом, не обновляется текущий каталог родительской оболочки. Является ли мой единственный способ создать новую оболочку в конце скрипта?

+0

Ваш скрипт 'test2' по-прежнему является отдельным * скриптом * и не работает в вашей интерактивной оболочке. Тот факт, что test2 внутренне имеет свою собственную функцию под названием 'mkcd', не изменяет того факта, что он запущен в подоболочке, которую вы создали, запустив' bash' в вашей интерактивной оболочке. Вместо запуска 'bash test2« Hello World », сделайте test2 функцией внутри вашей рабочей оболочки и запустите эту функцию. – ghoti

+0

То, что я пытаюсь сделать полностью, зависит от того, что это сценарий. –

+0

Теперь у вас есть несколько ответов, в том числе ваши собственные, и вы понимаете, почему у вас возникла проблема. Если вы действительно хотите изменить каталог в своей интерактивной оболочке на то, что создано вашим скриптом, существует несколько способов взлома, и я описал один в своем ответе. Является ли это применимым к вам, то, что я не могу знать, учитывая степень детализации вашего вопроса. – ghoti

ответ

3

Когда вы cd от в скрипте, ваш каталог изменяется внутри скрипта, но не внутри вызывающей оболочки.Рабочий каталог в вашей интерактивной оболочке устанавливается командами cd в оболочке THAT, а не внутри программ, которые ее запускают.

Если вы хотите, чтобы ваш скрипт мог изменить каталог вашей интерактивной оболочки, вам, вероятно, потребуется настроить функцию bash. Например, следующие могут быть добавлены к вашему .bash_profile:

mkcd() { 
    mkdir -p "$1" && cd "$1" 
} 

Так как эта функция работает в контексте интерактивной оболочки, а не порождая процесс подоболочку или ребенка, каталог изменения она сохраняется после выхода ,


Другим вариант, если вам нужно/хотят, чтобы сделать ваше создание каталога сценариев автономного инструмента, чтобы моделировать вещи после mktemp, который создает то, что ему нужно, а затем возвращает имя того, что он создал на стандартный вывод , Таким образом, с помощью следующего сценария, возможно, называется mkcd:

#!/bin/bash 

if mkdir -p "$*"; then 
    cd -P "$*" 
    pwd 
    r=0 
else 
    r=$? 
fi 

exit $r 

Затем в вызывающей сценарий, вы можете запустить это как:

#!/bin/bash 

d=$(mkcd Hello World) 

if [ ! -d "$d" ]; then 
    echo "ERROR: I can't go on like this" >&2 
    exit 1 
fi 

cd "$d" 
: do your stuff 

Обратите внимание, что проверка ошибок остается хорошей идеей, даже если она кажется избыточным, так как можно стать жертвой случайного или преднамеренного непредсказуемого поведения, если для создания имени каталога использовались специальные символы или нечетное форматирование.

+0

Итак, это должно быть помещено в '.bashrc' да? И затем, когда вы запускаете скрипт, он должен работать вне сценария, и я могу избежать появления тревожного количества сеансов за мой ответ. : P –

+0

В вашем '.bashrc' будет работать или ваш' .bash_profile', если он используется для интерактивного использования. Для использования в скрипте, который вы, например, запускаете из cron, можете просто добавить его в начало скрипта. Я не уверен в вашем случае использования, мы могли бы сделать это [проблема XY] (http://mywiki.wooledge.org/XyProblem) ... – ghoti

+0

Я столкнулся с каким-то странным поведением с этим. Я добавил его в '.bashrc' и получил желаемый результат, если я запускаю функцию непосредственно из оболочки, но если я запустил ее как скрипт, скрипт все равно выполнит ее и не повлияет на родительскую оболочку. –

-1

Ваш сценарий (в основном) в порядке, если вы используете cd "$1", как вы упомянули в вопросе. Проблема в том, что вам нужно убедиться, что полное имя каталога фактически передано как один аргумент.

$ bash test "Hello World" 

Затем в сценарии

# Omitting unused $wd 
# Omitting $fulldir, which appeared to be for debugging purposes only 
dir=$1 
mkdir -v "$dir" 
cd "$dir" 
+0

К сожалению, это тоже не меняет каталог. –

2

С немного больше исследований, я обнаружил, что это происходит потому, что сценарий представляет собой дочерний процесс и не может влиять на родительскую оболочку. Иными словами, скрипт будет работать в собственных целях. Я мог бы, например, изменить код к следующему:

#!/bin/bash 

dir=$1 
mkdir -v "$dir" 
cd "$dir" 
touch test.file 

И запустить

$ bash test "Hello World"

И результат был бы файл test.file появляющийся в ./Hello\ World/, однако, когда заканчивает сценарий, я все еще будет в предыдущем рабочем каталоге.

Небрежный способ получить результат, который я хотел, который находится в cd в новый каталог, заключается в том, чтобы создать новый сеанс в скрипте, используя exec bash.