is it possibe to change parent shell's working directory programmatically?

6,863

Solution 1

make mycd a function so the cd command executes in your current shell. Save it in your ~/.bashrc file.

function mycd {
    if (( $# == 0 )); then
        echo "usage: $FUNCNAME [1|2|3|...]"
        return
    fi
    case $1 in
        1) cd /tmp ;;
        2) cd /a/very/long/path/name ;;
        3) cd /some/where/else ;;
        *) echo "unknown parameter" ;;
    esac
}

Solution 2

You cannot change a shell's current directory from another process. Only the process itself can change its own current directory. This also holds for some other characteristics such as environment variables and file descriptors.

It is actually possible to affect another process's current directory by causing it to execute a chdir system call via the ptrace system call, which is what lets debuggers work. However, if the process maintains some internal data structures that have to be consistent with the actual current directory, the program is likely to crash. For a shell, this approach has no chance to work.

You need to arrange for your code to be executed by the shell itself. The normal way of proceeding would be to make it a shell function and store it in your ~/.bashrc. If this is not possible, for example because it's code that you want to distribute, write a shell source file that contains the function definition, and tell people to have their interactive shell read your file with the . command.

Solution 3

As you pointed out yourself, shell scripts are always executed in a subshell, which cannot influence its parent shell.

You can however...

  • use an alias:
    alias mycd2='cd /a/very/long/path/name'
  • have your script1 output a valid shell command ...

    #!/bin/bash
    if [ "x$1" = "x2" ]
    then
        echo "cd /a/very/long/path/name"
    fi
    

    ... and execute its output: $(mycd 2)

1: You'll probably want to use a case statement rather than the if condition in the example.

Share:
6,863

Related videos on Youtube

Javran
Author by

Javran

Updated on September 18, 2022

Comments

  • Javran
    Javran over 1 year

    I want to write some code to allow me switching to some directories that I usually go to. Say this program is mycd, and /a/very/long/path/name is the directory that I want to go to.

    So I can simply type mycd 2 instead of cd /a/very/long/path/name. Here I assume mycd knows 2 refers to that /a/very/long/path/name . There might also be mycd 1, mycd 3, ... etc.

    The problem is I have to write mycd as a shell script and type . mycd 2 to do the desired thing because otherwise the script just get executed in a child script which doesn't change anything about the parent shell that I actually care about.

    My question is:

    • can I do it without using source? because . mycd assumes mycd has to be a shell script and this might also introduce some functions that I don't want.

    • can I implement it in some other programming languages?

    • Admin
      Admin about 2 years
      On a practical note: Does adding some symlinks to e.g. home suffice?
  • Ricky
    Ricky over 10 years
    An alias is passable. A script is the same problem he already has. This question screams shell function.
  • Lekensteyn
    Lekensteyn over 10 years
    There is actually a chance to make it "work", but it is nontrivial, error-prone and should be avoided at all costs. To show that it is actually "possible", consider this shell script where the parent is Bash: ws=$1; gdb -p $(ps h -o ppid -p $$) -ex "call chdir(\"$wd\")" -ex "call set_working_directory(\"$wd\")" -ex detach -ex q -batch. Execute as braindead-cd-parent /. You will see that pwd returns / and so does ls, etc. behave. But the prompt (PS1) is still unchanged, people's eyes are hurt, etc. So do not do this even if it is possible.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 10 years
    @Lekensteyn That's the ptrace method I mention. It works well on programs that don't care much about their current directory. In a shell, a lot of things (PWD variable, prompt, etc.) are going to become wrong, and the shell may crash or otherwise misbehave.
  • Javran
    Javran over 10 years
    Thank you, haven't thought about using functions, and this just enables everything: I can now let mycd pass $@ to any program I like.
  • Angel Todorov
    Angel Todorov over 10 years
    Make sure you quote "$@" so that any arguments containing whitespace are handled correctly.