bash 用于创建和 cd 到名称中包含空格的目录的脚本

bash script to create and cd to directory with spaces in name

我正在开发一个项目,以在我的 GitLab CE 实例中远程创建一个存储库(该部分正在运行!),然后使用项目名称创建一个目录(正在运行!)并 cd 进入该目录(这是我遇到问题的地方......)然后在本地初始化并添加远程存储库(工作!!!)

我遇到的问题只是更改到新目录。无论我使用下面显示的代码,还是只是尝试 cd ""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

这段代码的输出是:

root@cana:~# ls
glnewproj  test
root@cana:~# bash test Hello World
Creating directory Hello World
mkdir: created directory 'Hello World'
Changing current directory to Hello World
Hello World
/root/Hello\ World/
root@cana:~# ls
Hello World  glnewproj  test
root@cana:~# pwd
/root

如何 cd 进入我新创建的目录?我完全被难住了。

编辑:

键入每个 ghoti 的函数并在 .bashrc 和我的测试脚本中对其进行测试。

当运行函数直接来自bash:

root@cana:~# ls
glnewproj  test  test2
root@cana:~# mkcd "Hello World"
root@cana:~/Hello World# 

当 运行 来自新测试脚本的函数时:

root@cana:~# ls
glnewproj  test  test2
root@cana:~# cat test2
#!/bin/bash

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

mkcd ""

root@cana:~# bash test2 "Hello World"
root@cana:~# ls
Hello World  glnewproj  test  test2

所以脚本仍然是 运行 的子脚本,因此不会更新父脚本 shell 的当前目录。我唯一的选择是在脚本末尾生成一个新的 shell 吗?

只要您按照问题中提到的那样使用 cd "",您的脚本(大部分)都很好。问题是您需要确保完整的目录名称实际上作为单个参数传递。

$ bash test "Hello World"

然后在你的脚本中

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

经过更多研究,我发现这是因为脚本是一个子进程,不能影响父进程 shell。也就是说,该脚本将 cd 用于它自己的目的。例如,我可以将代码更改为以下内容:

#!/bin/bash

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

和运行

$ bash test "Hello World"

结果是文件 test.file 出现在 ./Hello\ World/ 中,但是当脚本完成时,我仍会在之前的工作目录中。

获得我想要的结果的草率方法是 cd 到新目录,是使用 exec bash.

在脚本中生成一个新会话

当您从 在脚本 cd 时,您的目录会在脚本中更改,但不会在调用 shell 中更改。交互式 shell 中的工作目录是由 THAT shell 中的 cd 命令设置的,而不是在它 运行 的程序中设置的。

如果您希望您的脚本能够更改您的交互式 shell 的目录,那么您可能需要设置一个 bash 函数.例如,可以将以下内容添加到您的 .bash_profile

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

由于此函数 运行 在您的交互式 shell 的上下文中,而不是生成子 shell 或子进程,它所做的目录更改在退出后会保留.


另一种选择,如果您 need/want 使目录创建脚本成为一个独立的工具,那就是在 mktemp 之后建模,创建它需要的东西,然后 returns它创建到标准输出的名称。因此,使用以下脚本,可能称为 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

请注意,即使看起来多余,错误检查仍然是一个好主意,因为如果使用特殊字符或奇怪的格式来构建目录名称,则可能会成为意外或故意不可预测行为的受害者。