4

I would like to create an environment variable which is an "alias" of another environment variable. i.e. whenever the original variable changes, this alias variable changes with it. How do I do this in a robust way?

The exact situation for me is this: I use conda environments, which use an environment variable CONDA_DEFAULT_ENV that changes when you change environment. I would like an environment variable called VIRTUAL_ENV to be set and updated equal to CONDA_DEFAULT_ENV any time it changes.

Note that I'm using zsh on MacOS.

3
  • Have you thought about using a function instead of a variable for "VIRTUAL_ENV"? VIRTUAL_ENV() { echo "$CONDA_DEFAULT_ENV"; } Then use it like "$(VIRTUAL_ENV)" instead of "$VIRTUAL_ENV" Dec 30, 2021 at 20:07
  • I'd like to have it as a variable, because it is a standard variable for python virtual environments. However, conda doesn't use it (it uses CONDA_DEFAULT_ENV instead). Having VIRTUAL_ENV allows me to use themes which modify the prompt to display VIRTUAL_ENV in different ways.
    – ogb119
    Dec 30, 2021 at 21:00
  • Are both variables meant to be read by programs you don't control? And written to, too? Are they meant to be scalar? (Or arrays? Or something else?) Are they meant to be exported? Some half-solutions may work for you, depending on the answers to these questions (e.g. the hackish typeset -T CONDA_DEFAULT_ENV VIRTUAL_ENV '' or VIRTUAL_ENV=CONDA_DEFAULT_ENV + ${(P)VIRTUAL_ENV} when expanding).
    – fra-san
    Dec 30, 2021 at 21:31

1 Answer 1

1

The value of an environment variable is a string. Nothing fancier. There's no way to make programs automatically look at another variable: there's nothing for environment variables like symbolic links for files.

Zsh has some very limited facilities to customize the effects of changing a variable, but they won't help you here. (You'd have to write a custom module in C.) And anyway they would only work if you assign the variable in zsh.

What you can do is use a wrapper script around programs that use CONDA_DEFAULT_ENV. What I recommend is that you normally do not set CONDA_DEFAULT_ENV, and have the wrapper script set it if it's unset.

Put this script in a directory before /usr/bin in your $PATH, e.g. ~/bin/conda-wrapper. Make symbolic links to the script under the names of commands you want to wrap around, e.g. ln -s conda-wrapper ~/bin/conda. Then conda foo will set CONDA_DEFAULT_ENV and run /usr/bin/conda foo.

#!/bin/sh
if [ -z "$CONDA_DEFAULT_ENV" ] && [ -n "$VIRTUAL_ENV" ]; then
  export CONDA_DEFAULT_ENV="$VIRTUAL_ENV"
fi
exec "/usr/bin/${0##*/}" "$@"
4
  • Can you confirm what the "/usr/bin/${0##*/}" "$@" does? Do the characters get replaced with the name of the command and name of the command argument? e.g. in your example the ${0##*/} equates to conda and the $@ equates to foo?
    – ogb119
    Dec 31, 2021 at 15:00
  • @ogb119 Yes. ${0##*/} is the path to the script with all directories removed. "$@" is the list of arguments. Dec 31, 2021 at 15:45
  • Ok, thanks. This doesn't quite work, for some reason the first conda that gets picked up is not the symbolic link I create. Even though the symbolic link is in a folder at the beginning of $PATH. This is probably a quirk specific to conda!
    – ogb119
    Dec 31, 2021 at 18:17
  • @ogb119 Make sure to test in a new shell. Shells can cache command paths and not notice if a new executable by the same name is added earlier in the $PATH. Dec 31, 2021 at 19:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .