is it possibe to change parent shell's working directory programmatically?
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.
Related videos on Youtube
Javran
Updated on September 18, 2022Comments
-
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 ofcd /a/very/long/path/name
. Here I assumemycd
knows2
refers to that/a/very/long/path/name
. There might also bemycd 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
assumesmycd
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 about 2 yearsOn a practical note: Does adding some symlinks to e.g. home suffice?
-
Ricky over 10 yearsAn alias is passable. A script is the same problem he already has. This question screams shell function.
-
Lekensteyn over 10 yearsThere 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 asbraindead-cd-parent /
. You will see thatpwd
returns/
and so doesls
, 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' 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 over 10 yearsThank 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 over 10 yearsMake sure you quote
"$@"
so that any arguments containing whitespace are handled correctly.