为什么“ cd”在shell脚本中不起作用?


43

我只想编写一个可以更改目录的脚本。

我将以下命令放在文件中 /home/alex/pathABC

#!/bin/sh
cd /home/alex/Documents/A/B/C
echo HelloWorld

我做到了chmod +x pathABC

在终端中,在中/home/alex,我运行./pathABC,但输出仅为HelloWorld,当前目录未更改。

那怎么了?


Answers:


74

正如其他人所解释的那样,目录是在脚本的子进程中更改的,而不是在从中调用脚本的终端进程中更改的。子进程死亡后,您将返回到原来的终端。

几种选择:

1.符号链接

将符号链接放在您要轻松访问的长途之家中

$ ln -s /home/alex/Documents/A/B/C ~/pathABC

然后使用以下命令访问目录:

$ cd ~/pathABC

2.别名

在您的〜/ .bashrc中放置一个别名:

alias pathABC="cd /home/alex/Documents/A/B/C"

(从这里开始

3.功能

创建一个更改目录的函数,该函数将在终端进程中运行,然后可以更改其目录。

(从这里开始

4.避免小时候跑

编写脚本而不是运行脚本。源(由.或完成source)导致脚本在同一外壳中执行,而不是在其自己的子外壳中运行。

$ . ./pathABC

(从这里这里

5. CD-able vars

在中设置cdable_vars选项,~/.bashrc并在目录中创建一个环境变量:

shopt -s cdable_vars
export pathABC="/home/alex/Documents/A/B/C"

那你可以用 cd pathABC

(从这里开始


15
现在我明白了source!我一直想知道为什么我做的source .bashrc,而不是bash .bashrc
hytromo

选项3效果很好。我刚刚在脚本的开头定义了一个函数go_to_wherever(){cd my / directory}。在该目录中运行操作之前调用它。
i2097i

> 5. cd-able vars-是cd $pathABC吗?
loxaxs

7

在终端中运行脚本时,将运行一个子进程。在此子程序中,即您的脚本将更改为指定的目录。但是在父进程中,即您运行脚本的位置仍在旧路径中。或者简单地说:

The scope of cd command is only for child process not parent


2
添加到这一点,@alex实现你正在寻找的效果,执行脚本通过获取它的父进程:无论是. pathABCsource pathABC
zwets

4

您正在犯思维错误。当前外壳程序位于同一目录中时,脚本已移至新目录。

您可以通过在目录中创建另一个脚本并在更改目录后从您的脚本中运行该脚本来看到它:

#!/bin/sh
cd /home/alex/Documents/A/B/C && ./another_script.sh # (if it is executable)

第二个脚本将从新目录运行。

HelloWorld 

只是脚本的输出。


3
HelloWorld未“返回”到父外壳,而是输出到标准输出
Mog 2014年

如果仅pwd在新目录中运行,而不是向情况添加一个新的脚本,则可能会更清楚。
wjandrea

0

因为hello world只是一个trace语句,所以让我们尝试一下:

创建cd.sh包含以下内容的bash脚本文件:

#!/bin/bash
echo "/home/mike/Documents/A/B/C"
  • .sh扩展名是bash脚本文件名的扩展名的较早约定。这纯粹是化妆品,通常是不必要的。但是,在这种情况下,与核心cd命令区分开是很重要的。

使用以下命令将bash脚本文件标记为可执行文件:

chmod a+x cd.sh

现在运行文件:

$ cd $(./cd.sh)
bash: cd: /home/alex/Documents/A/B/C: No such file or directory
  • cd 我们都知道。
  • $(...) 在括号内执行命令并返回输出。
  • 如果cd.sh在您的路径中,则无需指定路径。我们以前缀./来指定命令在当前目录中。
  • 脚本的echo输出cd.sh通过传递回父级$(...)。父级(我们的shell提示)使用此输出,并将其传递给Linux cd命令。

正如其他人提到的那样,子进程无法更改父目录。这是孩子在程序结束后可以告诉父母去哪里的一种方法。


@wjandrea这就是您在电话上进行编码所得到的!刚到家,我会解决的。谢谢。嗯刚刚检查,它工作正常。14.04大概是一个小时左右前我读到的您的版本?
WinEunuuchs2Unix

好吧,您完全更改了脚本。以前,这只是一个命令:cd /home/mike/Documents/A/B/C,它不会产生任何输出。现在是echo "/home/mike/Documents/A/B/C",它会产生输出。
wjandrea

@wjandrea是的,我也完全改变了调用脚本的方式。./cd.sh现在cd $(./cd.sh),它不再是一个简单的方法,而是实现了子级更改父级当前目录的目标。是的,这是非常规的,但我希望人们能从中发现乐趣,这是另一种方式。
WinEunuuchs2Unix
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.