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?
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)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.
You can just type this in or put it in one of the various shell startup files.
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
in your .bashrc
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:
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:
and enter the text:
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).
Use
exec bash
at the endHowever, 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:
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.