2

I want to write a small script to source my virtualenv (for a Python project) directory. When I am somewhere inside my project directory, I know that the "venv" directory for my virtual environment is in a directory that is one of the ancestors of my current directory.

I want to write a shell script that will source venv/bin/activate and its effect should persist outside this shell script. This is not happening right now.

Here's my code:

#!/bin/bash

#set -x

while [ $PWD != "/" ]; do
    #echo $PWD
    if [ -d "venv" ]; then
        echo "venv found in $PWD. Sourcing."
        source venv/bin/activate
        break
    else
        cd ..
    fi
done

Why does it not work right now, and how can I fix it?

EDIT:

If it helps, the contents of venv/bin/activate are here: http://pastebin.com/TZ40brsq It is generated by the virtualenv tool (generally used with Python projects).

donatello
  • 5,727
  • 6
  • 32
  • 56
  • You have an relative path for your "source" command, which means that the script it will try to find the "venv" directory from within whichever directory the script is executing from. – jball037 Feb 04 '16 at 20:59

2 Answers2

3

You will have to invoke the script using

source path/to/script

or

. path/to/script

(same thing) rather than running it. It's a security measure that when you run a program, it cannot change the environment of its parent process (i.e. your shell session). However, when you use source, you're telling the shell to read the contents of the file and run it as if you had typed that contents yourself.

If you're already sourcing the script in this way, then I'm not sure what's going on.

David Z
  • 128,184
  • 27
  • 255
  • 279
  • `source` didn't work, `.` didn't either. The effect does not seem to persist outside this shell script. – donatello Dec 03 '12 at 07:42
  • Maybe it depends on the contents of venv/bin/activate. Could you add that in to your question? (or if it's more than a few lines, reduce it to a short example that demonstrates the problem) – David Z Dec 03 '12 at 11:22
  • Of course this "works" in the sense that the script which contains the `.` will now execute the code in the sourced file. What doesn't work is that a shell script's environment still does not persist after the shell which ran it has terminated. – tripleee Dec 31 '19 at 08:57
  • @tripleee Yes, agreed. But the way I read the question, it doesn't seem to be strictly required for the environment to persist after the shell has terminated, so I was suggesting a different way to get the effect it seems like the OP actually wants. – David Z Dec 31 '19 at 09:16
3

You cannot affect your current environment by using a shell script that runs in a child process.

If you add pushd "$(pwd)" before the while loop and popd after, you can get what you want by sourcing the script file instead of executing it

glenn jackman
  • 238,783
  • 38
  • 220
  • 352