7

This question already has an answer here:

When set command is used without any options, it displays the names and values of all shell variables and functions.

We want to display only the variables and avoid the functions from the output.

marked as duplicate by lesmana, Jeff Schaller, countermode, HalosGhost, don_crissti Dec 6 '16 at 18:10

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

14

As I already stated in a comment, env doesn't fit the requirement as it only shows exported variables.

Processing set output to filter out anything that doesn't look like a variable definition is an unreliable hack. You will in particular miss a part of variables which value contains a line feed. Even worst, a carefully written function can make appear fake variables definitions.

The simplest solution is to switch temporarily to the POSIX mode where functions are not considered to be (kind of) variables:

set -o posix
set
set +o posix

There is however an issue if your default mode is already POSIX, or if you want that command to work whatever POSIX mode the shell is set to.

In such case, here is a workaround:

(set -o posix;set)

This only set the POSIX mode for the set builtin executed in a subshell and the parent shell mode stay unaffected.

  • @jiliagre I guess even this would work set | grep -E '^\S+=\S'....right @terdon? – frp farhan Dec 6 '16 at 12:45
  • @FarhanPatel not for everything. See jlliagre's comment on my answer. This approach is better. – terdon Dec 6 '16 at 18:32
  • POSIX mode has the drawback of outputting multiline variables on multiple lines. While without POSIX mode, set outputs multiline variables as foobar=$'foo\nbar\nbaz' on a single line. Which is easier to parse then. – Antoine Pinsard Oct 14 '17 at 9:03
4

While the simplest solution is to use env instead of set, env doesn't give all existing variables but only those that would be passed to any process started with env (so no unexported variables, for example). Another approach is to search the output of set for lines that have a string of non-whitespace, an = and then another string of non-whitespace characters:

set | grep -E '^\S+=\S' 

However, this will miss any variables set to a multiline value (like IFS whose default value includes a \n).

  • 1
    @jlliagre indeed it is, there was a PEBKAC there. What can it miss though? Can you think of an example? – terdon Dec 6 '16 at 12:28
  • 2
    With the previous commands, you were missing by design all legitimate variables with names starting with an underscore. You are still missing a part of multiline content variables (e.g. IFS) so the output of your command is not parseable. Finally, you might display fake variables from function definitions. – jlliagre Dec 6 '16 at 12:48
  • Not to mention you run an external command while the shell is able to provide the already filtered output a more efficient way. – jlliagre Dec 6 '16 at 12:50
  • @jlliagre yes indeed. Very true for multiline vars, hadn't thought of that. But set doesn't print functions. At least not on my system. What kind of fake variables are you thinking of? – terdon Dec 6 '16 at 18:32
  • Bash set builtin print functions, that's the whole point of the OP question. Here is an example of such a fake variable: f() { a="a[ENTER]fubar=/tmp/gotcha[ENTER]b"; } . In fact, the same trick might also be used with multiline variables. – jlliagre Dec 6 '16 at 20:32
3

For some odd reason, declare -p seems to list only variables:

$ declare -p
declare -x ANT_HOME="/usr/share/apache-ant"
declare -- BASH="/usr/bin/bash"
declare -r BASHOPTS="checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:progcomp:promptvars:sourcepath"
declare -ir BASHPID
declare -A BASH_ALIASES=()
declare -a BASH_ARGC=()
declare -a BASH_ARGV=()
declare -A BASH_CMDS=()
...

Of course, this has the disadvantage that it outputs declare commands that can recreate the variable with all its attributes. Depending on what you intend to do with the output, that might actually be useful.

2

I'm not sure, but the cow would consider something.

 _____
( env )
 -----
        o   ^__^
         o  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

In other words, just use env instead.


I guess she's just read jilliagre's comment.

 ________________________________
/ But it will only show exported \
\ variables!                     /
 --------------------------------
        \   ^__^
         \  (!!)\_______
            (__)\       )\/\
             !! ||----w |
                ||     ||
  • :))) is this a RTFM cow? – Petr Matousu Dec 6 '16 at 11:10
  • 1
    env will only show exported variables. – jlliagre Dec 6 '16 at 11:16
  • @PetrMatousu I don't know her from that side. A word's been round she's getting into musing about please do my homework questions here. – Tomasz Dec 6 '16 at 11:18
  • @tomas, m new to shell scripting, could u pls explain me how this trick would achieve the objective. – frp farhan Dec 6 '16 at 11:28
  • 1
    @terdon, yes env prints only the global environment variables, however set without any options prints LOCAL and GLOBAL shell variables and functions.So both ain't same right? – frp farhan Dec 6 '16 at 11:32

Not the answer you're looking for? Browse other questions tagged or ask your own question.