pythonbashconda

Check if conda env exists and create if not in bash


I have a build script to run a simple python app. I am trying to set it up that it will run for any user that has conda installed and in their PATH. No other prerequisites. I have that pretty much accomplished but would like to make it more efficient for returning users.

build_run.sh

conda init bash
conda env create --name RUN_ENV --file ../run_env.yml -q --force
conda activate RUN_ENV
python run_app.py
conda deactivate

I would like to make it that the script checks if RUN_ENV already exists and activates it instead of forcing its creation every time. I tried

ENVS=$(conda env list | awk '{print }' )
if [[ conda env list = *"RUN_ENV"* ]]; then
   conda activate RUN_ENV
else 
   conda env create --name RUN_ENV --file ../run_env.yml -q
   conda activate RUN_ENV
   exit
fi;
python run_app.py
conda deactivate

but it always came back as false and tried to create RUN_ENV


Solution

  • update 2022

    i've been receiving upvotes recently. so i'm going to bump up that this method overall is not natively "conda" and might not be the best approach. like i said originally, i do not use conda. take my advice at your discretion.

    rather, please refer to @merv's comment in the question suggesting the use of the --prefix flag

    additionally take a look at the documentation for further details

    NOTE: you can always use a function within your bash script for repeated command invocations with very specific flags

    e.g

    function PREFIXED_CONDA(){
       action=${1};
       # copy $1 to $action;
       shift 1;
       # delete first argument and shift remaining indeces to the left
       conda ${action} --prefix /path/to/project ${@}
    }
    

    i am not sure how conda env list works (i don't use Anaconda); and your current if-tests are vague

    but i'm going out on a limb and guessing this is what you're looking for

    #!/usr/bin/env bash
    # ...
    find_in_conda_env(){
        conda env list | grep "${@}" >/dev/null 2>/dev/null
    }
    
    if find_in_conda_env ".*RUN_ENV.*" ; then
       conda activate RUN_ENV
    else 
    # ...
    

    instead of bringing it out into a separate function, you could also do

    # ...
    if conda env list | grep ".*RUN_ENV.*" >/dev/null 2>&1; then
    # ...
    

    bonus points for neatness and clarity if you use command grouping

    # ...
    if { conda env list | grep 'RUN_ENV'; } >/dev/null 2>&1; then
    # ...
    

    if simply checks the exit code. and grep exits with 0 (success) as long as there's at least one match of the pattern provided; this evaluates to "true" in the if statement

    (grep would match and succeed even if the pattern is just 'RUN_ENV' ;) )


    the awk portion of ENVS=$(conda env list | awk '{print }' ) does virtually nothing. i would expect the output to be in tabular format, but {print } does no filtering, i believe you were looking for {print $n} where n is a column number or awk /PATTERN/ {print} where PATTERN is likely RUN_ENV and only lines which have PATTERN are printed.

    but even so, storing a table in a string variable is going to be messing. you might want an array.

    then coming to your if-condition, it's plain syntactically wrong.