2016-04-03 217 views
1

我正在研究一個項目,在我的GitLab CE實例(該部分正在工作!)中遠程創建一個存儲庫,然後使用名稱項目(工作!)和光盤進入該目錄(這裏是我有問題...),然後在本地初始化並添加遠程存儲庫(工作!!!)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到我的新創建的目錄?我完全被難住了。

編輯:

打完了每ghoti功能和內.bashrc和我的測試腳本中進行了測試。

當直接從bash的運行功能:

[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 

所以腳本仍在運行作爲一個孩子,因此沒有更新父shell的當前目錄。我唯一的選擇是在腳本的末尾生成一個新的shell?

+0

您的'test2'腳本仍然是單獨的*腳本*,並且不在您的交互式shell中運行。 test2內部有一個名爲'mkcd'的函數不會改變它運行在通過在交互式shell中運行'bash'創建的子shell中的事實。而不是運行'bash test2「Hello World」,使test2成爲運行shell中的一個函數,並運行該函數。 – ghoti

+0

但是,我試圖完全取決於它是一個腳本。 –

+0

那麼,現在你有多個答案,包括你自己的答案,並且你明白你爲什麼遇到了問題。如果你真的想能夠將交互式shell中的目錄改變爲由腳本創建的目錄,那麼可以通過多種方式將它們合在一起,並且在我的答案中描述了一種方法。考慮到你的問題的細節程度,它是否適用於你是我不可能知道的。 – ghoti

回答

3

當您在腳本內的cd中,您的目錄在腳本內更改,但不在調用外殼內。交互式shell中的工作目錄由THAT shell中的cd命令設置,而不是由它運行的程序內部設置。

如果您希望您的腳本能夠更改交互式shell的目錄,那麼您可能需要設置一個bash 函數。例如,下面可以添加到您的.bash_profile

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

由於此功能時,您交互shell的上下文中運行,而不是產卵子shell或孩子的過程中,目錄的變化就不會被保留退出後。


另一種選擇,如果你需要/想使你的目錄中創建腳本一個獨立的工具,是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'中,並且如果直接從shell運行該函數,但是如果將它作爲腳本運行,則該腳本仍在執行,並且不會影響父shell。 –

-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

有了多一點的研究,我發現,這是因爲腳本是一個子進程,並不能影響父shell。也就是說,腳本會爲了自己的目的而裁剪。我可以,例如,代碼更改爲以下:

#!/bin/bash 

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

和運行

$ bash test "Hello World"

其結果將是出現在./Hello\ World/文件test.file,然而,當劇本完成後,我仍然會在之前的工作目錄中。

將我想要的結果(cdcd)的草率方式導入到新目錄中,是使用exec bash在腳本內產生新會話。