How to list all non-environment variables in bash?

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)

Add this to your ~/.bashrc

pre () {
    set -o posix;set > /tmp/tmp-original-envs
}

post () {
    set -o posix;set > /tmp/tmp-new-envs
    diff /tmp/tmp-original-envs /tmp/tmp-new-envs | grep -v BASH_LINENO | grep -v FUNCNAME | grep '>'
}

Then run pre before your modifications and post afterward

Example:

[localhost]$ pre
[localhost]$ test=new
[localhost]$ post
> test=new
[localhost]$