7

In trying to answer a question for another user, I came across something that piqued my curiosity:

import os
os.chdir('..')

Will change the working directory as far as Python is concerned, so if I am in /home/username/, and I run os.chdir('..'), any subsequent code will work as though I am in /home/. For example, if I then do:

import glob
files = glob.glob('*.py')

files will be a list of .py files in /home/ rather than in /home/username/. However, as soon as the script exits, I will be back in /home/username/, or whichever directory I ran the script from originally.

I have found the same thing happens with shell scripts. If I have the following script:

#!/bin/bash

cd /tmp
touch foo.txt

Running the script from /home/username/ will create a file foo.txt in /tmp/, but when the script finishes, I will still be in /home/username/ not /tmp/.

I am curious if there is some fundamental reason why the working directory is not changed "permanently" in these cases, and if there is a way to change it permanently, e.g., to run a script with ~$ python myscript.py, and have the terminal that script was run from end up in a different directory when the script finishes executing.

Community
  • 1
  • 1
elethan
  • 16,408
  • 8
  • 64
  • 87
  • 2
    This assumes every user who runs the scripts knows it will change their shell directory in the end, else the behavior will be quite if not slightly astonishing. – Moses Koledoye Sep 29 '16 at 18:26
  • @MosesKoledoye I didn't consider this. It would indeed be very confusing and dangerous if the user didn't know what was going on. I was thinking of a case where the user wanted and expected the behavior. Like maybe it is part of a workflow where after the script runs they need to do something in the shell, but in a different directory, and the script saves them the step of having to navigate there. – elethan Sep 29 '16 at 18:27
  • And I feel scripts should be more like sandboxes as regards the terminal/workspace, except of course there's an IO operation or an exception is thrown. Good question tho; thought*full*. – Moses Koledoye Sep 29 '16 at 18:31
  • 1
    Depends on your OS. Some versions of Windows have a `setx` console command that will make "permanent" changes to environment variables (and there's likely and underlying win32 API call that actually does it). – martineau Sep 29 '16 at 19:00
  • See [this answer](https://stackoverflow.com/questions/35843054/change-directory-in-terminal-using-python) – nos Feb 02 '18 at 16:17

1 Answers1

2

There is no way to do that because calling Python or bash will run everything within their own context (that ends when the script ends).

You could achieve those results by using source, since that will actually execute your (shell) script in the current shell. i.e., call your example script with source foomaker.bash instead of bash foomaker.bash

campos.ddc
  • 741
  • 5
  • 12
  • Very interesting! I didn't realize that `source` worked like that! So if `source` will execute the script in the current shell, where is the script executed normally? – elethan Sep 29 '16 at 18:36
  • 2
    If you call it with `bash foomaker.bash`, it will execute in a bash sub-shell. Basically it would be no different from running these commands in a row: `bash` (open a new bash shell) -> `cd foo` (cd inside the sub shell) -> `exit` (return to top level shell) – campos.ddc Sep 29 '16 at 18:39
  • Thanks! Yes, I was just now reading this: http://tldp.org/LDP/abs/html/subshells.html, which was helpful for me. – elethan Sep 29 '16 at 18:40