I cannot use cd anymore when using it in a bash script
[~/Downloads] # cat cd-backward #!/bin/bash cd .. [~/Downloads] # ./cd-backward [~/Downloads] # I should move to ~ at the last line.
cd works perfectly in terminal strangely. Nothing happens also when I run bash -c 'cd Download for instance.
3 Answers
Every script is executed in its own subshell, that is a separate process that cannot modify its parent working directory. The only way to change a working directory using a script written to a file is sourcing it using . or source (they are equivalent) like this:
$ . cd-backward or
$ source cd-backward Note that in such case you don't even need shebang (#!/bin/bash) at the top of your script.
When you launch a script, it runs in its own shell, as Arkadiusz already mentioned. In this case, you have instance of bash. You can see it if you modify the script:
#!/bin/bash cd .. pwd Sample run on my system gives :
bash-4.3$ pwd /home/xieerqi/Downloads bash-4.3$ ./cd-backward /home/xieerqi bash-4.3$ pwd /home/xieerqi/Downloads Appropriately enough, within the script subshell, you navigate to home directory. Parent shell's current working directory however remains unchanged
Your process (called $$) has a "Current directory", ~/Downloads.
When you ./cd-backward, that Bash script is run in its own process, which has its own "Current Directory", which starts off as ~/Downloads.
The cd .. affects the "Current Directory" of the ./cd-backward process, changing it to ~, but NOT affecting the "Current Directory" of your original process.
./cd-backward finishes, its process exits, and the cd .. is forgotten about.
Here are two ways I affect my own "Current Directory", kept in my '~/.bashrc`:
First, a couple of aliases:
alias ..='cd ..' alias ...='cd .. ; cd ..' Here's how I keep my current directory in my Window title (through intercepting cd):
# from the "xttitle(1)" man page - put info in window title update_title() { [[ $TERM = xterm ]] || [[ $TERM = xterm-color ]] && xttitle "[$$] ${USER}@${HOSTNAME}:$PWD" } cd() { [[ -z "$*" ]] && builtin cd $HOME [[ -n "$*" ]] && builtin cd "$*" update_title }