Why doesn't “cd” work in a shell script?

2018-12-31 01:44发布

I'm trying to write a small script to change the current directory to my project directory:

#!/bin/bash
cd /home/tree/projects/java

I saved this file as proj, added execute permission with chmod, and copied it to /usr/bin. When I call it by: proj, it does nothing. What am I doing wrong?

标签: linux shell
29条回答
唯独是你
2楼-- · 2018-12-31 02:20

Note the discussion How do I set the working directory of the parent process?

It contains some hackish answers, e.g. https://stackoverflow.com/a/2375174/755804 (changing the parent process directory via gdb, don't do this) and https://stackoverflow.com/a/51985735/755804 (the command tailcd that injects cd dirname to the input stream of the parent process; well, ideally it should be a part of bash rather than a hack)

查看更多
回忆,回不去的记忆
3楼-- · 2018-12-31 02:21

The cd in your script technically worked as it changed the directory of the shell that ran the script, but that was a separate process forked from your interactive shell.

A Posix-compatible way to solve this problem is to define a shell procedure rather than a shell-invoked command script.

jhome () {
  cd /home/tree/projects/java
}

You can just type this in or put it in one of the various shell startup files.

查看更多
伤终究还是伤i
4楼-- · 2018-12-31 02:21

I have a simple bash script called p to manage directory changing on
github.com/godzilla/bash-stuff
just put the script in your local bin directory (/usr/local/bin)
and put

alias p='. p'

in your .bashrc

查看更多
像晚风撩人
5楼-- · 2018-12-31 02:22

If you are using fish as your shell, the best solution is to create a function. As an example, given the original question, you could copy the 4 lines below and paste them into your fish command line:

function proj
   cd /home/tree/projects/java
end
funcsave proj

This will create the function and save it for use later. If your project changes, just repeat the process using the new path.

If you prefer, you can manually add the function file by doing the following:

nano ~/.config/fish/functions/proj.fish

and enter the text:

function proj
   cd /home/tree/projects/java
end

and finally press ctrl+x to exit and y followed by return to save your changes.

(NOTE: the first method of using funcsave creates the proj.fish file for you).

查看更多
残风、尘缘若梦
6楼-- · 2018-12-31 02:23

Use exec bash at the end

A bash script operates on its current environment or on that of its children, but never on its parent environment.

However, this question often gets asked because one wants to be left at a bash prompt in a certain directory after the execution of a bash script from another directory.

If this is the case, simply execute a child bash instance at the end of the script:

#!/bin/bash
cd /home/tree/projects/java
exec bash
查看更多
回忆,回不去的记忆
7楼-- · 2018-12-31 02:24

When you fire a shell script, it runs a new instance of that shell (/bin/bash). Thus, your script just fires up a shell, changes the directory and exits. Put another way, cd (and other such commands) within a shell script do not affect nor have access to the shell from which they were launched.

查看更多
登录 后发表回答