9

I'm trying to change the terminal directory through a python script. I've seen this post and others like it so I know about os.chdir, but it's not working the way I'd like. os.chdir appears to change the directory, but only for the python script. For instance I have this code.

#! /usr/bin/env python
import os

os.chdir("/home/chekid/work2/")
print os.getcwd()

Unfortunately after running I'm still in the directory of the python script (e.g. /home/chekid) rather than the directory I want to be in. See below.

gandalf(pts/42):~> pwd
/home/chekid

gandalf(pts/42):~> ./changedirectory.py
/home/chekid/work2

gandalf(pts/42):~> pwd
/home/chekid

Any thoughts on what I should do?

Edit: Looks like what I'm trying to do doesn't exist in 'normal' python. I did find a work around, although it doesn't look so elegant to me.

 cd `./changedirectory.py`
Community
  • 1
  • 1
che_kid
  • 203
  • 2
  • 6
  • The python script changes it's own directory. Bash doesn't change. Note that what are you asking is the same as assuming that if you open a file in a python script, the file should also open on your desktop – smac89 Dec 04 '15 at 18:20
  • 2
    You cannot do it. That's why `cd` is always a shell built-in command, not an external program. – chepner Dec 04 '15 at 18:20
  • Maybe you'd like to use `os.system()`? – Santosh Kumar Dec 04 '15 at 18:20
  • See http://stackoverflow.com/questions/2375003/how-do-i-set-the-working-directory-of-the-parent-process – Linuxios Dec 04 '15 at 18:24
  • 1
    @SantoshKumar: Won't work, `system` sort of "runs its own shell". – Linuxios Dec 04 '15 at 18:24
  • A little more looking reveals that while **still a *bad* idea**, this can be done (relatively) simply through some calls to `gdb`: https://rudd-o.com/linux-and-free-software/the-shell-challenge-changing-another-process-working-directory. That link lists the caveats: `bash` doesn't realize it's CWD has been changed, and so on. – Linuxios Dec 04 '15 at 18:32
  • In Bash you can make an alias, like this: `alias mycd="cd \`./changedirectory.py\`"` – Peer Sommerlund Jun 21 '22 at 08:12

4 Answers4

6

You can't. The shell's current directory belongs to the shell, not to you.

(OK, you could ptrace(2) the shell and make it call chdir(2), but that's probably not a great design, won't work on Windows, and I would not begin to know how to do it in pure Python except that you'd probably have to mess around with ctypes or something similar.)

You could launch a subshell with your current working directory. That might be close enough to what you need:

os.chdir('/path/to/somewhere')
shell = os.environ.get('SHELL', '/bin/sh')
os.execl(shell, shell)
# execl() does not return; it replaces the Python process with a new shell process

The original shell will still be there, so make sure you don't leave it hanging around. If you initially call Python with the exec builtin (e.g. exec python /path/to/script.py), then the original shell will be replaced with the Python process and you won't have to worry about this. But if Python exits without launching the shell, you'll be left with no shell open at all.

Kevin
  • 28,963
  • 9
  • 62
  • 81
  • That sounds like a fun project :-). I guess if you could find the code area you could do, basically, a code injection attack. Huh. – Linuxios Dec 04 '15 at 18:27
  • @Linuxios: I'm not sure I'd call it an "attack," exactly. You're basically just doing the gdb trick by hand. – Kevin Dec 05 '15 at 06:17
4

You can if you cheat: Make a bash script that calls your python script. The python script returns the path you want to change directory to. Then the bash script does the acctual chdir. Of course you would have to run the bash script in your bash shell using "source".

Peer Sommerlund
  • 502
  • 6
  • 14
  • For more inspiration, take a look at this list of NCD clones http://www.softpanorama.org/OFM/norton_change_directory_clones.shtml – Peer Sommerlund Jun 21 '22 at 08:15
3

The current working directory is an attribute of a process. It cannot be changed by another program, such as changing the current working directory in your shell by running a separate Python program. This is why cd is always a shell built-in command.

chepner
  • 497,756
  • 71
  • 530
  • 681
-1

You can make your python print the directory you want to move to, and then call your script with cd "$(./python-script.py)". In condition your script actually does not print anything else.