2016-04-03 71 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在脚本内产生新会话。