What's the best practice for changing working directories inside scripts?


Do you think changing directories inside bash or Perl scripts is acceptable? Or should one avoid doing this at all costs?

What is the best practice for this issue?

10/27/2008 8:11:51 PM

Accepted Answer

The current working directory is local to the executing shell, so you can't affect the user unless he is "dotting" (running it in the current shell, as opposed to running it normally creating a new shell process) your script.

A very good way of doing this is to use subshells, which i often do in aliases.

alias build-product1='(cd $working-copy/delivery; mvn package;)'

The paranthesis will make sure that the command is executed from a sub-shell, and thus will not affect the working directory of my shell. Also it will not affect the last-working-directory, so cd -; works as expected.

10/27/2008 5:19:16 PM

Like Hugo said, you can't effect your parent process's cwd so there's no problem.

Where the question is more applicable is if you don't control the whole process, like in a subroutine or module. In those cases you want to exit the subroutine in the same directory as you entered, otherwise subtle action-at-a-distance creeps in which causes bugs.

You can to this by hand...

use Cwd;
sub foo {
    my $orig_cwd = cwd;
    chdir "some/dir";

    ...do some work...

    chdir $orig_cwd;

but that has problems. If the subroutine returns early or dies (and the exception is trapped) your code will still be in some/dir. Also, the chdirs might fail and you have to remember to check each use. Bleh.

Fortunately, there's a couple modules to make this easier. File::pushd is one, but I prefer File::chdir.

use File::chdir;
sub foo {
    local $CWD = 'some/dir';

    ...do some work...

File::chdir makes changing directories into assigning to $CWD. And you can localize $CWD so it will reset at the end of your scope, no matter what. It also automatically checks if the chdir succeeds and throws an exception otherwise. Sometimes it use it in scripts because it's just so convenient.

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow