Differences between revisions 5 and 8 (spanning 3 versions)
Revision 5 as of 2008-11-22 14:09:50
Size: 2378
Editor: localhost
Comment: converted to 1.6 markup
Revision 8 as of 2011-01-27 10:15:26
Size: 2765
Editor: wks24
Comment: Added slightly more involved example as the OP wanted to write "scripts".
Deletions are marked like this. Additions are marked like this.
Line 3: Line 3:
Line 5: Line 4:
Line 30: Line 28:

Lastly you can also use aliasses to do the same. Put into your `~/.bashrc` something like
{{{
   alias cdtmp="cd /tmp"
}}}
and typing {{{cdtmp}}} will take your current shell to {{{/tmp}}}. Slightly more complicated aliasses are possible like
{{{
   alias cdlstmp="cd /tmp; ls tmp*"
}}}
which will take you to {{{/tmp}}} and show you what files there are starting with {{{tmp}}}.

I'm trying to write a script that will change directory (or set a variable), but after the script finishes, I'm back where I started (or my variable isn't set)!

Consider this:

   #!/bin/sh
   cd /tmp

If one executes this simple script, what happens? Bash forks, resulting in a parent (the interactive shell in which you typed the command) and a child (a new shell that reads and executes the script). The child runs, while the parent waits for it to finish. The child reads and executes the script, changes its current directory to /tmp, and then exits. The parent, which was waiting for the child, harvests the child's exit status (presumably 0 for success), and then carries on with the next command. Nowhere in this process has the parent's current working directory changed -- only the child's.

A child process can never affect any part of the parent's environment, which includes its variables, its current working directory, its open files, its resource limits, etc.

So, how does one go about changing the current working directory of the parent? You can still have the cd command in an external file, but you can't run it as a script. That would cause the forking explained earlier. Instead, you must source it with . (or the Bash-only synonym, source). Sourcing basically means you execute the commands in a file using the current shell, not in a forked shell (child shell):

   echo 'cd /tmp' > "$HOME/mycd"  # Create a file that contains the 'cd /tmp' command.
   . $HOME/mycd                   # Source that file, executing the 'cd /tmp' command in the current shell.
   pwd                            # Now, we're in /tmp

The same thing applies to setting variables. . ("dot in") the file that contains the commands; don't try to run it.

If the command you execute is a function, not a script, it will be executed in the current shell. Therefore, it's possible to define a function to do what we tried to do with an external file in the examples above, without needing to "dot in" or "source" anything. Define the following function and then call it simply by typing mycd:

   mycd() { cd /tmp; }

Put it in ~/.bashrc or similar if you want the function to be available automatically in every new shell you open.

Lastly you can also use aliasses to do the same. Put into your ~/.bashrc something like

   alias cdtmp="cd /tmp"

and typing cdtmp will take your current shell to /tmp. Slightly more complicated aliasses are possible like

   alias cdlstmp="cd /tmp; ls tmp*"

which will take you to /tmp and show you what files there are starting with tmp.

BashFAQ/060 (last edited 2014-04-27 04:35:48 by ormaaj)