How to change the current directory using cd from a Bash script permanently

I got a bash script and when it exit to shell I need to stay in new directory. The script

#!/bin/bash
now=$(date --date="last month" +"%b-%Y")
src=$(date --date="2 month ago" +"%b-%Y")

[ -d "$now" ] && { echo "$0: '${now}' found and nothing to do. bye."; exit 1; }

mkdir -vp "$now"
[ -d "$src" ] && cp -a $src/* "$now"
find "$now" -type f -delete 
cd "$now"

The last line never work:

cd "$now"

How do I make sure script to change current directory using cd when exit to the current shell?

Call your script as:

source /path/to/script

Instead of:

/path/to/script
bash /path/to/script
sh /path/to/script

This will execute all commands from a file in the current shell. But when you run the /path/to/script, all command will execute in the subshell. So you need use the source command.

2 Likes

Simple yet yet elegant solution. I would never have guessed it.

Do check source command examples Source command - Linux Shell Scripting Wiki

1 Like

Need to remember that vars defined in a script run by source carry over to the existing shell, which depending on the var name might cause unwanted side effects, meaning that if you use the same var name in another script without reassigning the contents or deleting the var it’ll break your code.

1 Like

I didn’t know that. Is there any way to make those variable set in shell variable to go away. Is unset is a good idea?

unset var1
unset var2
unset my_function_1
unset my_function_2
# do the final cd?
cd "/my/dir"

Untested, but I suppose you could cheat it even when sourceing by wrapping your code inside the script into parenthesis, which indicates wanting to start a new shell (like when you run bash myscript.sh) whereas the wave brackets indicate running in the same shell, hence the problem with var persistence.

^ Considering an extra shell doesn’t use all that many resources and doesn’t take an age to create 2 new ones in a row (especially if using Dash instead of Bash), such a hack doesn’t really make things worse.

^ IMO that’s way better than taking care to delete the vars before exiting the script.

Like so:

#!/bin/bash
(
now=$(date --date="last month" +"%b-%Y")
src=$(date --date="2 month ago" +"%b-%Y")

[ -d "$now" ] && { echo "$0: '${now}' found and nothing to do. bye."; exit 1; }

mkdir -vp "$now"
[ -d "$src" ] && cp -a $src/* "$now"
find "$now" -type f -delete 
cd "$now"
)
1 Like

I try your solution but it didn’t worked out. Thank you for the input.

How not ?

(Stupid 20-char minimum limit)

When script exit I need to be in the “$now” directory. So I copy your script example and ran it as follows:

source myscript.sh

It created the directory but cd "$now" never worked.

Subshell substitution:
cat myscript.sh:

#!/bin/bash
cd ..
exec bash

Run:

echo $$ $PWD
24276 /home/nez/bash/nixcraft/test
exec ./myscript.sh
echo $$ $PWD
24276 /home/nez/bash/nixcraft
2 Likes

This one also works.


Linux sysadmin blog - Linux/Unix Howtos and Tutorials - Linux bash shell scripting wiki