Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Checking if a variable is exported

84 views
Skip to first unread message

Martijn Dekker

unread,
Oct 21, 2016, 10:25:43 PM10/21/16
to
I'm looking for ways for scripts to check, as efficiently as possible,
if a variable is exported. Shell-specific ways are very welcome if they
are more efficient than what's possible in the standard POSIX shell.

On zsh it's trivial: the expansion ${(t)var} yields dash-separated type
information keywords for $var, including the word "export" if the
variable is exported. Even better, ${(Pt)1} yields that info for the
variable whose name is in $1.

Does anyone know of any efficient ways on other shells? TIA for any
pointers.

(People not interested in background info can stop reading here.)

An obvious generic way could be to do something like:
case $(exec sh -c 'echo "${var+s}"') in
( s ) [it was exported] ;;
esac
to see if 'var' survives the exec. But that's not reliable; shells
initialise various variables on startup.

POSIX shells do allow listing all the exported variables. The 'export
-p' command produces 'export' commands for all the currently exported
variables, in a "format suitable for re-entry into the shell". The
problem there is that only the shell itself can reliably parse them.
Using grep or sed is not reliable; the printed values may contain
newline characters, and if those contain things that look like variable
names you once again have false positives.

The workaround I've figured out is to temporarily alias "export" to a
handler function, then do
eval "$('export' -p)"
(quoting "export" to get around the alias) and then unalias "export"
again. The handler function gets called as many times as there are
exported variables, with the arguments meant for the 'export' commands,
so all you need to do is set a flag variable if one matches the one
you're looking for.

On zsh this method has two problems:
(1) 'export -p' produces 'typeset' commands, not 'export' commands, even
if the shell is in POSIX mode [however, it's just as easy to alias
'typeset' as well; the handler function just needs to skip the options
with shift $((${#}-1))];
(2) in recent zsh versions, both 'export' and 'typeset' became reserved
words so the alias is ignored [however, 'disable -r' can be used to
temporarily disable these reserved words, revealing the underlying
builtins].
Not that this matters, because zsh has a much better way. I don't know
of any other shells that have 'export' as a reserved word.

Thanks,

- M.

Rakesh Sharma

unread,
Oct 22, 2016, 3:24:00 AM10/22/16
to
On Saturday, 22 October 2016 07:55:43 UTC+5:30, Martijn Dekker wrote:

>
> I'm looking for ways for scripts to check, as efficiently as possible,
> if a variable is exported. Shell-specific ways are very welcome if they
> are more efficient than what's possible in the standard POSIX shell.
>
> Does anyone know of any efficient ways on other shells? TIA for any
> pointers.
>

printenv "var" >/dev/null 2>&1 && echo "The variable 'var' is exported."

Rakesh Sharma

unread,
Oct 22, 2016, 5:53:59 AM10/22/16
to
On Saturday, 22 October 2016 07:55:43 UTC+5:30, Martijn Dekker wrote:

>
> I'm looking for ways for scripts to check, as efficiently as possible,
> if a variable is exported. Shell-specific ways are very welcome if they
> are more efficient than what's possible in the standard POSIX shell.
>
> Does anyone know of any efficient ways on other shells? TIA for any
> pointers.
>
> An obvious generic way could be to do something like:
> case $(exec sh -c 'echo "${var+s}"') in
> ( s ) [it was exported] ;;
> esac
> to see if 'var' survives the exec. But that's not reliable; shells
> initialise various variables on startup.
>

A reliable way is to do a 3-step process:
a) inside a subshell, first make sure that $var survives, as you've done.
b) next blank out $var.
c) source the startup file & now check whether $var survived.


sh -c '
case ${var+s} in
( s )
unset var
. $HOME/.profile
${var+:} echo "var exported";;
esac
'

Martijn Dekker

unread,
Oct 22, 2016, 8:35:54 AM10/22/16
to
Op 22-10-16 om 11:53 schreef Rakesh Sharma:
> A reliable way is to do a 3-step process:
> a) inside a subshell, first make sure that $var survives, as you've done.
> b) next blank out $var.
> c) source the startup file & now check whether $var survived.
>
>
> sh -c '
> case ${var+s} in
> ( s )
> unset var
> . $HOME/.profile
> ${var+:} echo "var exported";;
> esac
> '

That will check if the variable was set in ~/.profile, nothing else. It
won't check if:
- the variable was exported in ~/.profile;
- the variable was set or exported someplace else (like by the shell
itself, in /etc/profile, in the current script itself or another script
it is using).

What I'm looking for is ways (including shell-specific ways) to check
the shell's actual internal "export" flag on variables that are more
efficient than parsing the output of 'export -p'.

Thanks anyway,

- M.

Martijn Dekker

unread,
Oct 22, 2016, 8:38:14 AM10/22/16
to
Op 22-10-16 om 09:23 schreef Rakesh Sharma:
> printenv "var" >/dev/null 2>&1 && echo "The variable 'var' is exported."

This gets closer to what I want than your other reply. Unfortunately
this way also has a couple of problems:

- 'printenv' is a non-standard external utility (though it seems to be
pretty ubiquitous). Launching an external process is not that efficient
and I can't count on the command being present.

- It does not show variables that are exported but unset.

It makes sense that unset exported variables don't actually make it out
into the external environment, but I still want my function to work for
them. So I am looking for ways (including shell-specific ways) that are
internal to the shell but more efficient than parsing the output of
'export -p'.

Thanks for the reply,

- M.

Kenny McCormack

unread,
Oct 22, 2016, 8:40:00 AM10/22/16
to
In article <e714p7...@mid.individual.net>,
Martijn Dekker <mar...@inlv.demon.nl> wrote in response to a glob of
shell code:
...
>What I'm looking for is ways (including shell-specific ways) to check
>the shell's actual internal "export" flag on variables that are more
>efficient than parsing the output of 'export -p'.
>
>Thanks anyway,

It seems clear to me that the "printenv" method is the best so far.
Compact and foolproof.

Not sure why Rakeesh felt the need to post again (with this goofball mass
of shell scripting) when he had already given the definitive answer.

--
Mike Huckabee has yet to consciously uncouple from Josh Duggar.

Kenny McCormack

unread,
Oct 22, 2016, 8:47:26 AM10/22/16
to
In article <e714tj...@mid.individual.net>,
Martijn Dekker <mar...@inlv.demon.nl> wrote:
>Op 22-10-16 om 09:23 schreef Rakesh Sharma:
>> printenv "var" >/dev/null 2>&1 && echo "The variable 'var' is exported."
>
>This gets closer to what I want than your other reply. Unfortunately
>this way also has a couple of problems:
>
>- 'printenv' is a non-standard external utility (though it seems to be
>pretty ubiquitous). Launching an external process is not that efficient
>and I can't count on the command being present.

Technically true, but almost certainly irrelevant.

>- It does not show variables that are exported but unset.

True. I was able to test/verify this assertion. Seems a pretty convoluted
thing to worry about, though.

>It makes sense that unset exported variables don't actually make it out
>into the external environment, but I still want my function to work for
>them. So I am looking for ways (including shell-specific ways) that are
>internal to the shell but more efficient than parsing the output of
>'export -p'.

Then you may be stuck. Your requirements are sufficiently restrictive
that parsing the output of 'export' (in one form or another) is probably
the only thing that will work.

--
The randomly chosen signature file that would have appeared here is more than 4
lines long. As such, it violates one or more Usenet RFCs. In order to remain in
compliance with said RFCs, the actual sig can be found at the following web address:
http://www.xmission.com/~gazelle/Sigs/Seneca

Martijn Dekker

unread,
Oct 22, 2016, 9:59:23 AM10/22/16
to
Op 22-10-16 om 14:47 schreef Kenny McCormack:
> In article <e714tj...@mid.individual.net>,
> Martijn Dekker <mar...@inlv.demon.nl> wrote:
>> - 'printenv' is a non-standard external utility (though it seems to be
>> pretty ubiquitous). Launching an external process is not that efficient
>> and I can't count on the command being present.
>
> Technically true, but almost certainly irrelevant.

Not if you've set yourself the challenge to write a cross-platform POSIX
shell library that needs to work on *all* the shells on *all* the OSes
(assuming full POSIX compliance, with tolerance for certain specific
bugs). A standards-compliant fallback method is mandatory.

(For anyone interested, development is ongoing at
<https://github.com/modernish/modernish>.)

*launching VM* ... Yup, Solaris doesn't have printenv.

[...]
> Then you may be stuck. Your requirements are sufficiently restrictive
> that parsing the output of 'export' (in one form or another) is probably
> the only thing that will work.

I suspected as much, but it's always possible I might be missing a
feature somewhere in shells like bash or ksh. Hence my post.

Parsing 'export -p' by aliasing 'export' works as a fallback method, as
long as 'export' is not a reserved word, so for now I'm happy enough.
I'm just hoping shells other than zsh, which don't have the ability to
disable reserved words, won't decide to make it a reserved word in the
future (which violates the standard, by the way).

Thanks,

- M.

Janis Papanagnou

unread,
Oct 22, 2016, 11:04:03 AM10/22/16
to
On 22.10.2016 15:59, Martijn Dekker wrote:
>
> [ write a cross-platform POSIX shell library ]
>
> I suspected as much, but it's always possible I might be missing a
> feature somewhere in shells like bash or ksh. Hence my post.

Curious; how do you make that match, cross-platform and using
individual shell's features?

Janis

Martijn Dekker

unread,
Oct 22, 2016, 2:44:55 PM10/22/16
to
Op 22-10-16 om 17:04 schreef Janis Papanagnou:
> Curious; how do you make that match, cross-platform and using
> individual shell's features?

In this particular case, using a combination of:
- a test 'eval' in a subshell to determine if the shell has the relevant
zsh-style parameter expansion;
- wrapping the function definitions that use this feature in 'eval' so
they don't cause syntax errors on other shells;
- and using the modernish thisshellhas() function, which (among other
things, like running bug/feature tests and caching their results) is
capable of checking for the presence of a reserved word on all POSIX shells.

Below is my code for defining the internal functions that handle
'isset -x', the option for 'isset' to check if a variable is exported.

If you want to know how thisshellhas() or other things work, go to
Github and read the code, or just grab a copy (disclaimers: under heavy
development, no release version exists yet, breakage and incompatible
changes *will* happen, keep 'git pull'-ing and reading 'git log' and
'git log -p'):

$ git clone https://github.com/modernish/modernish
$ modernish/install.sh # if /bin/sh is POSIX compliant
$ dash modernish/install.sh # otherwise use a shell that is
$ . modernish # for interactive use

Documentation (such as it is) is in README.md and share/doc/modernish/,
but at this point you just may have to read the code as well. Bug
reports and constructive criticism are welcome!

Oops. I think I just made the first public announcement. Oh well, here
goes nothing...

- M.

(Note: _Msh_* is the namespace for internal functions and variables that
shall not be touched or directly used by programs using the library.)

___begin code (warning: long lines; I'm long over the 80s)___
# Internal functions for isset -x
if isset ZSH_VERSION && ( eval ': ${(t)PATH}' ) 2>/dev/null; then
# zsh makes this trivial: ${(t)VARNAME} (dash-separated)
contains 'export',
# and the P in ${(Pt)1} means: use the variable name stored in
$1. Good thing
# because 'export' on zsh is a reserved word we cannot alias
(see below).
if thisshellhas --rw=[[; then
# '[[' could have been disabled with 'disable -r' so
don't assume it.
eval '_Msh_issetEx() {
[[ -${(Pt)1}- == *-export-* ]]
}'
else # If you disable POSIX keywords like 'case', you never
even get this far.
eval '_Msh_issetEx() {
case -${(Pt)1}- in ( *-export-* ) ;; ( * )
return 1 ;; esac
}'
fi
elif ! thisshellhas --rw=export; then
# On other shells, we must use trickery to reliably parse the
output of 'export -p'.
# The 'export -p' command in POSIX shells produces 'export'
commands (even on bash, as
# long as the shell is in POSIX mode, which it must be to run
modernish). Grepping this
# output is not reliably possible because entries may be split
in multiple lines. We
# must get the shell to parse it. The only way to do this is to
temporarily alias
# 'export' to a handler function. This only works if 'export' is
not a reserved word.
_Msh_issetEx() {
unset -v _Msh_issetEx_WasRun _Msh_issetEx_FoundIt
export _Msh_issetEx_Dummy=foo # guarantee one exported
variable to check if this method works
_Msh_issetExV=$1
alias export=_Msh_issetExHandleExport
eval "$(command export -p)"
unalias export
unset -v _Msh_issetExV _Msh_issetEx_Dummy
isset _Msh_issetEx_WasRun && unset -v _Msh_issetEx_WasRun ||
die "isset -x: internal error: 'export -p' not
parseable (is shell in POSIX mode?)" || return
isset _Msh_issetEx_FoundIt && unset -v _Msh_issetEx_FoundIt
}
_Msh_issetExHandleExport() {
_Msh_issetEx_WasRun=''
case ${1%%=*} in
("${_Msh_issetExV}") _Msh_issetEx_FoundIt='' ;;
esac
}
else _Msh_initExit "init: isset -x: Can't determine method to test if
a var. is exported." \
"This shell has 'export' as a reserved word, but
modernish was only" \
"programmed to handle this on zsh. Please report this as
a bug in modernish."
fi
___end code___

Rakesh Sharma

unread,
Oct 22, 2016, 2:55:43 PM10/22/16
to
On Saturday, 22 October 2016 18:05:54 UTC+5:30, Martijn Dekker wrote:

>
> > sh -c '
> > case ${var+s} in
> > ( s )
> > unset var
> > . $HOME/.profile
> > ${var+:} echo "var exported";;
> > esac
> > '
>
> That will check if the variable was set in ~/.profile, nothing else. It
> won't check if:
> - the variable was exported in ~/.profile;
> - the variable was set or exported someplace else (like by the shell
> itself, in /etc/profile, in the current script itself or another script
> it is using).
>

Actually it's slightly subtler than you at first think.
No, tt won't check if a variable was set in the .profile.
Firstly, you need to realize that shell variables that are not exported
will not come into play in the sh -c '...' construct. Only the variables
that are exported will show up. Coz sh -c does not read the .profile.
So... when we perform the case ${var+s} inside the sh -c '...' => that
var will be an exported variable if at all it matches the 's' portion of the
case-esac block.
The sourcing of ~/.profile should follow a sourcing of /etc/profile
Finally the ${var+:} construct will turn ON only in case of an exported
var in the shell script which have been unset one step apriori. And not
for the case of an exported var in the startup files (the ~/.profile /etc/profile).

Coz: That's what I understood that you wanted to just find the exported
variables that are coming from the script. From your comment you wrote
shown below. So it appeared to me that the startup exported variables
needed to thrown away.

>
> An obvious generic way could be to do something like:
> case $(exec sh -c 'echo "${var+s}"') in
> ( s ) [it was exported] ;;
> esac
> to see if 'var' survives the exec. But that's not reliable; shells
> initialise various variables on startup.
>

Actually there a many ways to find out what you are looking for, viz.,
just the ENVIRONMENT variables.

1. Can you believe that the infamous csh has a succinct way to find it out:

csh -fc 'unset var; if ( $?var ) echo "var exported"'


2. make utility can be of help here.

case $(echo 'all:; @printf "%s\n" "$(origin var)"' | make -f -) in
'environment' ) :;; * ) false;;
esac && echo "var is exported"

3. grep/cmp combo can be used to diff-parse the export -p output reliably.

tf=`mktemp`
export -p > $tf
if grep '^export var=' < $tf >/dev/null 2>&1
then
# could be false +ve due to multiline variable
# contents sneakily matching a valid export syntax!!
unset var
export -p | cmp -s - $tf || echo "var exported"
fi
rm -f "$tf"

-Rakesh

Rakesh Sharma

unread,
Oct 22, 2016, 3:03:29 PM10/22/16
to
On Saturday, 22 October 2016 18:08:14 UTC+5:30, Martijn Dekker wrote:


>
> > printenv "var" >/dev/null 2>&1 && echo "The variable 'var' is exported."
>
> This gets closer to what I want than your other reply. Unfortunately
> this way also has a couple of problems:
>
> - 'printenv' is a non-standard external utility (though it seems to be
> pretty ubiquitous). Launching an external process is not that efficient
> and I can't count on the command being present.
>


>
> - It does not show variables that are exported but unset.
>
Now what on earth does the above mean? Once a variable is unset
it goes out of the pool of environment variables or shell variables.
Even doing an "export -p" WON't show that.
So I am not sure what you are wanting to do.

Rakesh Sharma

unread,
Oct 22, 2016, 3:30:29 PM10/22/16
to
Another way could be which calls no external utilities:

eval "`echo 'NL=qnq' | tr 'qn' '\47\12'`"
case $(export -p) in
'export var='* | *"${NL}export var="* )
case "$(unset var;export -p)" in
"$(export -p)" ) :;;
* ) echo "var exported";;
esac;;
esac

-Rakesh

Martijn Dekker

unread,
Oct 22, 2016, 3:45:35 PM10/22/16
to
Op 22-10-16 om 21:03 schreef Rakesh Sharma:
> Now what on earth does the above mean? Once a variable is unset
> it goes out of the pool of environment variables or shell variables.
> Even doing an "export -p" WON't show that.

Actually, it will.

On POSIX shells, yes, 'unset -v varname' will unset and unexport the
variable, but a subsequent 'export varname' will set the variable name's
export flag without setting the variable.

For instance, on dash:

$ unset foo; export foo; export -p

will include "export foo" in the output, without the '=', to indicate
that this is an exported unset variable.

This is also explicitly specified by POSIX:

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_22_03

| When -p is specified, export shall write to the standard output the
| names and values of all exported variables, in the following format:
|
| "export %s=%s\n", <name>, <value>
|
| if name is set, and:
|
| "export %s\n", <name>
|
| if name is unset.

So yes, believe it or not, there is such a thing as an exported unset
variable.

- M.

Rakesh Sharma

unread,
Oct 22, 2016, 10:20:17 PM10/22/16
to
You seem to have too much free time looks like!

Your problem can be very simply solved using shell-builtins
only, as follows:

__Msh_issetx() {
case $# in
1 ) case $1 in '' | *[!a-zA_Z0-9_]* | [0-9]* ) >&2 echo "bad var name"; exit 2;; esac;;
* ) echo >&2 "only 1 arg"; exit 1;;
esac

( # Open a subshell to localize changes to superglobals
# and also be allowed to use shell variables that are
# erased once done, i.e., they behave as locals.
varname=$1
eval "`echo 'NL=qnq' | tr 'qn' '\47\12'`"
IFS=$NL
set -f
set X $(export -p); N1=$#
set X $(unset -v "$varname"; export -p); N2=$#
case $N1 in "$N2" ) exit 3;; esac; exit 0;
); return "$?"
}

# stub
__Msh_issetx
__Msh_issetx "bad-var-name"
__Msh_issetx 'var' && echo 'var exported'


But the neatest way to do the problem is:
sh -c 'case ${var++} in ? ) echo "var exported";; esac'

Martijn Dekker

unread,
Oct 23, 2016, 5:05:45 AM10/23/16
to
Op 22-10-16 om 21:30 schreef Rakesh Sharma:
> Another way could be which calls no external utilities:
>
> eval "`echo 'NL=qnq' | tr 'qn' '\47\12'`"

FYI, for newline I have ${CCn} in modernish.

> case $(export -p) in
> 'export var='* | *"${NL}export var="* )
> case "$(unset var;export -p)" in
> "$(export -p)" ) :;;
> * ) echo "var exported";;
> esac;;
> esac

Yeah, comparing the complete output of 'export -p' with and without
unsetting will work. I've used a similar strategy for 'isset -f', which
checks if a function is set.

Actually I think the inner 'case' is sufficient:

case "$(unset var;export -p)" in
"$(export -p)" ) :;;
* ) echo "var exported";;
esac

I think the point of your outer 'case' is to avoid forking two command
substitution shells by first checking if we need to do this at all, but
that comes at the cost of forking one of its own.

I care a lot about performance. Forks are hugely expensive, almost as
much as launching an external utility. A subshell fork takes longer than
a thousand shell function calls (except if you're on AT&T ksh93, which
does subshells without forking, but that's just one shell). The way with
aliasing 'export' does one fork so it's faster.

However, I'll add your way as a fallback to the fallback, in case any
non-zsh shell ever gets 'export' as a reserved word.

Thanks,

- M.

Martijn Dekker

unread,
Oct 23, 2016, 5:18:45 AM10/23/16
to
Op 23-10-16 om 04:20 schreef Rakesh Sharma:
> Your problem can be very simply solved using shell-builtins
> only, as follows:

That was hardly what I would call simple, and it has no performance
advantage over your simpler way either.


> But the neatest way to do the problem is:
> sh -c 'case ${var++} in ? ) echo "var exported";; esac'

As I pointed out in my original post, that's unreliable; shells
initialise their own variables (and it varies by shell which they are).

Thanks,

- M.

Martijn Dekker

unread,
Oct 23, 2016, 6:40:03 AM10/23/16
to
Op 22-10-16 om 21:30 schreef Rakesh Sharma:
> case "$(unset var;export -p)" in
> "$(export -p)" ) :;;
> * ) echo "var exported";;
> esac;;

Another thing: this doesn't work for readonly variables, because you
can't unset those. Variables can be both exported and readonly.

- M.

Rakesh Sharma

unread,
Oct 24, 2016, 3:56:42 PM10/24/16
to
Yes that's correct, I didn't look at the readonly vars.

I have come up with a fallback function in case your aliasing mechanism fails on
some shells for commands being not alias-able.


################################## <code> ######################################

case $# in
2 ) :;;
* ) echo >&2 "Usage: $0 shell_name variable_name"; exit 1;;
esac

case $1 in
'' | 'sh' | 'zsh' | 'bash' ) this_shell=${1:-sh};;
* ) echo >&2 "Invalid shell '$1'. Choose from: [sh|zsh|bash]"; exit 1;;
esac

Exp=$($this_shell -c 'export -p') # generate the export list
${Exp:+:} exit 1; # just in case we have nothing exported, bail out

cmd=${Exp%%[ ]*} # grab the command used by your shell for recreating

case $2 in
'' | *[!0-9a-zA-Z_]* | [0-9]* ) echo >&2 "Invalid shell variable name: '$2'"; exit 2;;
* ) varname=$2;;
esac

eval "`echo 'NL=qnq' | tr 'qn' '\47\12'`"

Exp1=${Exp/$cmd /_Msh_issetx_fb $varname }
Exp2=${Exp1//$NL$cmd / \\${NL}|| _Msh_issetx_fb $varname }

_Msh_issetx_fb() {
search_varname=$1; shift

case $* in
*[=]* )
# grab 1st argument that contains an =
while case $# in 0 ) break;; esac
do
case $1 in
*[=]* ) case ${1%%=*} in "$search_varname" ) echo "Variable $search_varname exported"; return 0;; esac ;;
esac
shift
done;;

* ) # grab the last arg in case no = found: this is the unset exported variable
case ${1##*[ ]} in "$search_varname" ) echo "Variable $search_varname exported"; return 0;; esac;;
esac

return 1
}

eval "$Exp2"
############################### </code> #################################

Rakesh Sharma

unread,
Oct 24, 2016, 4:02:28 PM10/24/16
to
What I want to reiterate & emphasize is that inside sh -c '....' only exported
variables from the calling environment are visible. So if you are talking about
non-exported variables, aka, shell variables, being set in the startup files, then
they will not be visible. Hence your concern is groundless.

Rakesh Sharma

unread,
Oct 24, 2016, 4:11:09 PM10/24/16
to
we can pre-store the results in a variable:

exp0=$(export -p)
case $exp0 in
'export var='* | *"${NL}export var="* )
case "$(unset var;export -p)" in
"$exp0" ) :;;

Rakesh Sharma

unread,
Oct 25, 2016, 1:25:31 AM10/25/16
to
On Sunday, 23 October 2016 16:10:03 UTC+5:30, Martijn Dekker wrote:

>
> > case "$(unset var;export -p)" in
> > "$(export -p)" ) :;;
> > * ) echo "var exported";;
> > esac ;;
>
> Another thing: this doesn't work for readonly variables, because you
> can't unset those. Variables can be both exported and readonly.
>

Actually this case can be handled as well if we take a look at the status
of the "unset" command. From the opengroup manual on "unset" we see that:

*************
EXIT STATUS
0
All name operands were successfully unset.
>0
At least one name could not be unset.
*************

# generate the export list
Exp=$(export -p)

# then attempt an unset of the variable
_ro_flag=1
unset -v "varname" 2>/dev/null || _ro_flag=

# now generate the export list again & test for equality
case $(export -p) in
"$Exp") # could be due to readonly effect or var is not an exported variable
${_ro_flag:+:} echo "var is exported";;
* ) echo "var is exported";;
esac
echo /Fini.

Martijn Dekker

unread,
Oct 26, 2016, 2:30:47 PM10/26/16
to
Op 24-10-16 om 21:01 schreef Rakesh Sharma:
> What I want to reiterate & emphasize is that inside sh -c '....' only exported
> variables from the calling environment are visible. So if you are talking about
> non-exported variables, aka, shell variables, being set in the startup files, then
> they will not be visible. Hence your concern is groundless.

Actually my concern is trivial to prove right. Note that 'env -i'
completely clears the environment before launching the command (sh -c
'set' in this case).

$ env -i sh -c 'set'
BASH=/bin/sh
BASH_ARGC=()
BASH_ARGV=()
BASH_EXECUTION_STRING=set
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="3" [1]="2" [2]="57" [3]="1" [4]="release"
[5]="x86_64-apple-darwin15")
BASH_VERSION='3.2.57(1)-release'
DIRSTACK=()
EUID=504
GROUPS=()
HOSTNAME=breedzicht
HOSTTYPE=x86_64
IFS='
'
MACHTYPE=x86_64-apple-darwin15
OPTERR=1
OPTIND=1
OSTYPE=darwin15
PATH=/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin:.
POSIXLY_CORRECT=y
PPID=58235
PS4='+ '
PWD=/Users/martijn
SHELL=/bin/bash
SHELLOPTS=braceexpand:hashall:interactive-comments:posix
SHLVL=1
TERM=dumb
UID=504
_=sh

Rakesh Sharma

unread,
Oct 27, 2016, 12:06:54 AM10/27/16
to
I don't see any of these variables in the startup files (.profile, /etc/profile).

So where are they coming from? And neither are the startup files being
read/sourced in the sh -c '...' invocation. That could mean only one thing,
that these variables are hard coded within the /bin/sh binary.
0 new messages