Bash – How to list all non-environment variables in bash

bashechovariable

I'd like to echo all non-environment variables (all self-declared variables), in Bash 3.2.52.

This command to print all variables gave me output I can't understand that seems to me to conflict with the set -x && clear -r mode I already work in.

diff -U 1 <(set -o posix ; set |cut -d= -f1) <(
    exec bash -ic 'set -o posix ; set' | cut -d= -f1)  |
        grep '^[-][^-]'                                |
        cut -d- -f2                                    |
        grep -vE '^(COLUMNS|HISTFILESIZE|HISTSIZE|LINES|PIPESTATUS)$'

I need an echo or printf (or any other "simpler") operation to have such list.
If possible in this version of Bash, how can this be achieved?

Best Answer

  • GNU Parallel includes env_parallel. Part of env_parallel lists all variables for the supported shells.

    For bash this code is:

    _names_of_VARIABLES() {
        compgen -A variable
    }
    _bodies_of_VARIABLES() {
        typeset -p "$@"
    }
    

    So given all variables we need to figure out which ones are set by the user. We can do that by hardcoding all variables set by a given version of bash, but that would not be very future proof, because bash may set more variables in future versions (Is $BASH_MYVAR set by the user or by a future version of bash?).

    So instead env_parallel asks you to define a clean environment, and run env_parallel --session in that. This will set $PARALLEL_IGNORED_NAMES by listing the names defined before (using the code above).

    When later run in an environment where the user has set variables, it is easy to take the difference between the clean environment and the current environment.

    env_parallel --session makes it possible to define a clean environment for every session, but if you prefer to have a reference environment that can be used across sessions, simply save the list of variables to a file. So:

    # In clean envronment
    compgen -A variable > ~/.clean-env-vars
    
    # In environment with user defined vars
    compgen -A variable | grep -Fxvf ~/.clean-env-vars
    

    For example:

    #!/bin/bash
    
    # In clean envronment
    compgen -A variable > ~/.clean-env-vars
    
    myvar=4
    yourvar=3
    
    # In environment with user defined vars
    compgen -A variable | grep -Fxvf ~/.clean-env-vars
    
    # This prints:
    # myvar
    # yourvar
    # PIPESTATUS (which is set when running a pipe)
    
  • Related Question