Change the current directory from a Bash script
-
22-08-2019 - |
Question
Is it possible to change current directory from a script?
I want to create a utility for directory navigation in Bash. I have created a test script that looks like the following:
#!/bin/bash
cd /home/artemb
When I execute the script from the Bash shell the current directory doesn't change. Is it possible at all to change the current shell directory from a script?
Solution
You need to convert your script to a shell function:
#!/bin/bash
#
# this script should not be run directly,
# instead you need to source it from your .bashrc,
# by adding this line:
# . ~/bin/myprog.sh
#
function myprog() {
A=$1
B=$2
echo "aaa ${A} bbb ${B} ccc"
cd /proc
}
The reason is that each process has its own current directory, and when you execute a program from the shell it is run in a new process. The standard "cd", "pushd" and "popd" are builtin to the shell interpreter so that they affect the shell process.
By making your program a shell function, you are adding your own in-process command and then any directory change gets reflected in the shell process.
OTHER TIPS
When you start your script, a new process is created that only inherits your environment. When it ends, it ends. Your current environment stays as it is.
Instead, you can start your script like this:
. myscript.sh
The .
will evaluate the script in the current environment, so it might be altered
In light of the unreadability and overcomplication of answers, i believe this is what the requestor should do
- add that script to the
PATH
- run the script as
. scriptname
The .
(dot) will make sure the script is not run in a child shell.
Putting the above together, you can make an alias
alias your_cmd=". your_cmd"
if you don't want to write the leading "." each time you want to source your script to the shell environment, or if you simply don't want to remember that must be done for the script to work correctly.
If you are using bash you can try alias:
into the .bashrc file add this line:
alias p='cd /home/serdar/my_new_folder/path/'
when you write "p" on the command line, it will change the directory.
If you run a bash script then it will operates on its current environment or on those of its children, never on the parent.
If goal is to run your command : goto.sh /home/test Then work interactively in /home/test one way is to run a bash interactive subshell within your script :
#!/bin/bash
cd $1
exec bash
This way you will be in /home/test until you exit ( exit or Ctrl+C ) of this shell.
With pushd the current directory is pushed on the directory stack and it is changed to the given directory, popd get the directory on top of the stack and changes then to it.
pushd ../new/dir > /dev/null
# do something in ../new/dir
popd > /dev/null
Simply go to
yourusername/.bashrc (or yourusername/.bash_profile on MAC) by an editor
and add this code next to the last line:
alias yourcommand="cd /the_path_you_wish"
Then quit editor.
Then type:
source ~/.bashrc or source ~/.bash_profile on MAC.
now you can use: yourcommand in terminal
I've made a script to change directory. take a look: https://github.com/ygpark/dj
Basically we use cd..
to come back from every directory. I thought to make it more easy by giving the number of directories with which you need to come back at a time. You can implement this using a separate script file using the alias command . For example:
code.sh
#!/bin/sh
_backfunc(){
if [ "$1" -eq 1 ]; then
cd ..
elif [ "$1" -eq 2 ]; then
cd ../..
elif [ "$1" -eq 3 ]; then
cd ../../..
elif [ "$1" -eq 4 ]; then
cd ../../../..
elif ["$1" -eq 10]; then
cd /home/arun/Documents/work
fi
}
alias back='_backfunc'
After using source code.sh
in the current shell you can use :
$back 2
to come two steps back from the current directory. Explained in detail over here. It is also explained over there how to put the code in ~/.bashrc so that every new shell opened will automatically have this new alias command. You can add new command to go to specific directories by modifying the code by adding more if conditions
and different arguments. You can also pull the code from git over here.
This approach is easier for me.
Suppose on a personal iMac where you are an admin, under the default directory when a command window is opened, /Users/jdoe, this will be the directory to go to: /Users/jdoe/Desktop/Mongo/db.3.2.1/bin.
These are the steps that can have the job done:
- vi mongobin, in which I entered:
cd /Users/jdoe/Desktop/Mongo/db.3.2.1/bin
as the first line. chmod 755 mongobin
source mongobin
pwd
Voila!
I've also created a utility called goat that you can use for easier navigation.
You can view the source code on GitHub.
As of v2.3.1 the usage overview looks like this:
# Create a link (h4xdir) to a directory:
goat h4xdir ~/Documents/dev
# Follow a link to change a directory:
cd h4xdir
# Follow a link (and don't stop there!):
cd h4xdir/awesome-project
# Go up the filesystem tree with '...' (same as `cd ../../`):
cd ...
# List all your links:
goat list
# Delete a link (or more):
goat delete h4xdir lojban
# Delete all the links which point to directories with the given prefix:
goat deleteprefix $HOME/Documents
# Delete all saved links:
goat nuke
# Delete broken links:
goat fix
I like to do the same thing for different projects without firing up a new shell.
In your case:
cd /home/artemb
Save the_script as:
echo cd /home/artemb
Then fire it up with:
\`./the_script\`
Then you get to the directory using the same shell.
Add below cd line in your shellscript this:
exec $SHELL
Declare your path:
PATH='/home/artemb'
cd ${PATH}