Is the export command behaviour different in sh and in bash?

Clash Royale CLAN TAG#URR8PPP
up vote
6
down vote
favorite
I have a shell script without the first line that specifies which shell type to use to interpret commands.
This .sh file has been used on a SCO Unix 5 system until the moment of migration on a more modern system like RHEL 7.
It seems to me that sh is the default shell in SCO Unix while the bash is the default shell in Red Hat Linux, so I think that porting the script to linux and running it, this one will be interpreted by default with the bash.
Coming to the point, in this script there is a section like this:
MY_SETUP=1
echo $MY_SETUP
MY_SETUP=2 export MYSETUP
echo $MY_SETUP
As you can see the name of the variable after the export command is not the one in the assignment (it was a typing mistake).
I noticed that the value of MY_SETUP variable after this section is different if the script is interpreted by sh or bash.
sh MY_SETUP value = 2
bash MY_SETUP value = 1
It seems that bash completely ignores the assignment inline with the export command and keeps the previous value.
All this run without returning any error, so I was wondering why there is a different behavior. Can someone explain me?
EDIT:
From Stéphane Chazelas answer it seems that in bash this instruction
var=x export var
doesn't set the "x"value and doesn't export it, but in my environment it does both. I'm confused.
bash shell
add a comment |Â
up vote
6
down vote
favorite
I have a shell script without the first line that specifies which shell type to use to interpret commands.
This .sh file has been used on a SCO Unix 5 system until the moment of migration on a more modern system like RHEL 7.
It seems to me that sh is the default shell in SCO Unix while the bash is the default shell in Red Hat Linux, so I think that porting the script to linux and running it, this one will be interpreted by default with the bash.
Coming to the point, in this script there is a section like this:
MY_SETUP=1
echo $MY_SETUP
MY_SETUP=2 export MYSETUP
echo $MY_SETUP
As you can see the name of the variable after the export command is not the one in the assignment (it was a typing mistake).
I noticed that the value of MY_SETUP variable after this section is different if the script is interpreted by sh or bash.
sh MY_SETUP value = 2
bash MY_SETUP value = 1
It seems that bash completely ignores the assignment inline with the export command and keeps the previous value.
All this run without returning any error, so I was wondering why there is a different behavior. Can someone explain me?
EDIT:
From Stéphane Chazelas answer it seems that in bash this instruction
var=x export var
doesn't set the "x"value and doesn't export it, but in my environment it does both. I'm confused.
bash shell
You're right about your edit, looks like I messed up my tests, I'll update my answer.
â Stéphane Chazelas
Jun 8 at 11:42
add a comment |Â
up vote
6
down vote
favorite
up vote
6
down vote
favorite
I have a shell script without the first line that specifies which shell type to use to interpret commands.
This .sh file has been used on a SCO Unix 5 system until the moment of migration on a more modern system like RHEL 7.
It seems to me that sh is the default shell in SCO Unix while the bash is the default shell in Red Hat Linux, so I think that porting the script to linux and running it, this one will be interpreted by default with the bash.
Coming to the point, in this script there is a section like this:
MY_SETUP=1
echo $MY_SETUP
MY_SETUP=2 export MYSETUP
echo $MY_SETUP
As you can see the name of the variable after the export command is not the one in the assignment (it was a typing mistake).
I noticed that the value of MY_SETUP variable after this section is different if the script is interpreted by sh or bash.
sh MY_SETUP value = 2
bash MY_SETUP value = 1
It seems that bash completely ignores the assignment inline with the export command and keeps the previous value.
All this run without returning any error, so I was wondering why there is a different behavior. Can someone explain me?
EDIT:
From Stéphane Chazelas answer it seems that in bash this instruction
var=x export var
doesn't set the "x"value and doesn't export it, but in my environment it does both. I'm confused.
bash shell
I have a shell script without the first line that specifies which shell type to use to interpret commands.
This .sh file has been used on a SCO Unix 5 system until the moment of migration on a more modern system like RHEL 7.
It seems to me that sh is the default shell in SCO Unix while the bash is the default shell in Red Hat Linux, so I think that porting the script to linux and running it, this one will be interpreted by default with the bash.
Coming to the point, in this script there is a section like this:
MY_SETUP=1
echo $MY_SETUP
MY_SETUP=2 export MYSETUP
echo $MY_SETUP
As you can see the name of the variable after the export command is not the one in the assignment (it was a typing mistake).
I noticed that the value of MY_SETUP variable after this section is different if the script is interpreted by sh or bash.
sh MY_SETUP value = 2
bash MY_SETUP value = 1
It seems that bash completely ignores the assignment inline with the export command and keeps the previous value.
All this run without returning any error, so I was wondering why there is a different behavior. Can someone explain me?
EDIT:
From Stéphane Chazelas answer it seems that in bash this instruction
var=x export var
doesn't set the "x"value and doesn't export it, but in my environment it does both. I'm confused.
bash shell
edited Jun 8 at 11:32
asked Jun 7 at 15:11
alessaro
343
343
You're right about your edit, looks like I messed up my tests, I'll update my answer.
â Stéphane Chazelas
Jun 8 at 11:42
add a comment |Â
You're right about your edit, looks like I messed up my tests, I'll update my answer.
â Stéphane Chazelas
Jun 8 at 11:42
You're right about your edit, looks like I messed up my tests, I'll update my answer.
â Stéphane Chazelas
Jun 8 at 11:42
You're right about your edit, looks like I messed up my tests, I'll update my answer.
â Stéphane Chazelas
Jun 8 at 11:42
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
2
down vote
It seems that you detected a POSIX deviation in bash that is also a deviation from the historic Bourne Shell. You may call it a bug or a just deviating behavior.
The script you refer to prints
1
2
with all shells except bash in default behavior.
If you call bash --posix, it works correctly.
From a pointer from user Kusalananda it seems that bash by default makes all builtin commands restore their temporary environment at exit and not just for the non-special builtins. Since export is a special builtin, POSIX requires a shell to behave the same as a Bourne Shell from the early 1980s end to keep the environment value.
Since bash does not implement this by default, you get the deviation.
bashin its POSIX mode does the right thing though.
â Kusalananda
Jun 7 at 15:22
Point 30 in Chet's list of differences betweenbash's default mode of operation andbash --posixmay be relevant, possibly.
â Kusalananda
Jun 7 at 15:27
It would be a bug if it didn't work as documented. Herebashbehaves as required by POSIX when in POSIX mode, like when called assh, and works as documented (and some would argue in a less surprising way) otherwise.
â Stéphane Chazelas
Jun 7 at 15:36
Note thatzshbehaves likebashhere, so it's not all shells except bash.
â Stéphane Chazelas
Jun 7 at 15:38
I testedzsh, so it may be that zsh changed behavior between different releases.
â schily
Jun 7 at 15:40
 |Â
show 5 more comments
up vote
0
down vote
Yes, the behavior is different. The whole description is not so simple.
First: when is it equal?
This code line :
$ var=1; printf "%s" "$var"; var=2 export var; echo " $var"
Will print 1 2 in all (non-csh like) shells except zsh.
jsh : 1 2 # ATT version sh (heirloom).
ash : 1 2
yash : 1 2
dash : 1 2
zsh/sh : 1 2
bash : 1 2
posixbash : 1 2
lksh : 1 2
mksh : 1 2
ksh93 : 1 2
attsh : 1 2
zsh : 1 1
That looks like a mistake of zsh to me. How could be reasonable that exporting a variable does not retain the exported value ?
But that is because the exported variable: var, is the same var that is printed.
Exporting some other var.
If the line is changed to something more similar to what you are asking, with some other varname, like this:
$ var=1; printf "%s" "$var"; var=2 export othervar; echo " $var"
The difference(s) become clear:
jsh : 1 2
dash : 1 2
bash : 1 1
posixbash : 1 2
ksh93 : 1 2
zsh : 1 1
It is clear that bash is different to old sh (Bourne), newer sh (dash), ksh and others (not listed here).
But what is more important is that bash acts differently than bash --posix.
Posix requirement.
Some of the shell builtins (not all) are called "special built-ins":
From: 2.14. Special Built-In Utilities
The following "special built-in" utilities shall be supported in the shell command language.
⦠however, the special built-in utilities described here differ from regular built-in utilities in two respects:
An error in a special built-in utility may cause a shell executing that utility to abort, while an error in a regular built-in utility shall not cause a shell executing that utility to abort. â¦
As described in Simple Commands, variable assignments preceding the invocation of a special built-in utility remain in effect after the built-in completes; this shall not be the case with a regular built-in or other utility.
So, in a simple command: var=2 specialBuiltin the variable var should retain its value after the specialBuiltin has exited. But not all shell implementations follow such rule.
So, this should print 1 hello 2 (as eval is an special builtin):
var=1; printf '%s ' "$var"; var=2 eval printf %s hello; echo " $var"
It does in sh and bash --posix but not in plain bash.
List of special builtins.
In fact, The POSIX list of special builtins is here, the list being:
02 break
03 :
04 .
05 continue
06 eval
07 exec
08 exit
09 export
10 readonly
11 return
12 set
13 shift
14 times
15 trap
16 unset
The number in first column is the value of var used for each test.
We could test all special builtins (except exit, exec and times) with this code:
var=01;
while : ; do var=02 break; done; printf ' %s' "02-$var"; var=01
var=03 : ; printf ' %s' "03-$var"; var=01
echo 'printf " %s" "04-<$var>"' >source-sh
var=04 . source-sh; printf ' %s' "04-$var"; var=01
c=0; while ((c++<1)); do
var=05 continue
done; printf ' %s' "05-$var"; var=01
var=06 eval 'printf " %s" "06-<$var>"'; printf ' %s' "06-$var"; var=01
#( var=07 exec bash -c 'printf " %s" "07-$var"'); var=01
#( var=08 exit; printf ' %s' "08-$var" ); var=01
var=09 export var; printf ' %s' "09-$var"; var=01
var=10 readonly i; printf ' %s' "10-$var"; var=01
varfun() var=11 return; ; varfun; printf ' %s' "11-$var"; var=01
var=12 set -- aa ; printf ' %s' "12-$var"; var=01
var=13 shift; printf ' %s' "13-$var"; var=01
var=15 trap; printf ' %s' "14-$var"; var=01
var=16 unset j; printf ' %s' "15-$var"; var=01
echo
To print this list:
jsh : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
dash : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
bash : 02-01 03-01 04-<04> 04-01 05-01 06-<06> 06-01 09-09 10-01 11-01 12-01 13-01 15-01 16-01
posixbash : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
ksh93 : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
zsh : 02-01 03-01 04-<04> 04-01 05-01 06-<06> 06-01 09-01 10-01 11-01 12-01 13-01 15-01 16-01
As you can see, where posix request that var retain 02 most shells retain it and print 02-02, but not in bash (nor zsh) as they print 02-01. Only in export is bash printing 09-09 and zsh printing 09-01.
So you're saying that in my case bash doesn't keep the value assigned because, since the "export var" command used individually makes a variable visible in the subprocesses and since the bash with the default behavior doesn't take into account special builtins, my bash takes care of exporting the name of the variable that doesn't match with the one assigned, losing the value?
â alessaro
Jun 11 at 7:04
Please do not claim to have a complete list of Bourne-alike shells if you miss important implementations. For an expressive comparison, it is sufficient to list the ones that are most important and/or well maintained. These are: bash dash bosh mksh ksh88 ksh93 zsh I am not sure wether yash should be in that list because of many deviations. zsh also has many deviations and dash cannot be used on a full blown UNIX system since it misses support for multi-byte characters.
â schily
Jun 11 at 9:16
Let me add a note to the heirloom shell. It has been derived from the SunOS Bourne Shell and modified in various undocumented ways. It is not portable and it is unmaintained. In fact, there was no more than 3 months of work from the maintainer. If you like to verify the behavior of the SunOS Bourne Shell, it is better to use the "osh" binary compiled from the bosh sources, since that is very close to the SunOS original and portable.
â schily
Jun 11 at 9:19
@alessaro "Your case" is not theexport varcase. In the later case, the first I cover, bothshandbashact exactly the same. "Your case" is the second I cover.
â Isaac
Jun 11 at 16:25
@schily I am very (very) sorry for your pain. ... But the only thing that matters here is wether "the Bourne shell" prints1 1or1 2, the rest are just opinions.
â Isaac
Jun 11 at 16:33
 |Â
show 4 more comments
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
It seems that you detected a POSIX deviation in bash that is also a deviation from the historic Bourne Shell. You may call it a bug or a just deviating behavior.
The script you refer to prints
1
2
with all shells except bash in default behavior.
If you call bash --posix, it works correctly.
From a pointer from user Kusalananda it seems that bash by default makes all builtin commands restore their temporary environment at exit and not just for the non-special builtins. Since export is a special builtin, POSIX requires a shell to behave the same as a Bourne Shell from the early 1980s end to keep the environment value.
Since bash does not implement this by default, you get the deviation.
bashin its POSIX mode does the right thing though.
â Kusalananda
Jun 7 at 15:22
Point 30 in Chet's list of differences betweenbash's default mode of operation andbash --posixmay be relevant, possibly.
â Kusalananda
Jun 7 at 15:27
It would be a bug if it didn't work as documented. Herebashbehaves as required by POSIX when in POSIX mode, like when called assh, and works as documented (and some would argue in a less surprising way) otherwise.
â Stéphane Chazelas
Jun 7 at 15:36
Note thatzshbehaves likebashhere, so it's not all shells except bash.
â Stéphane Chazelas
Jun 7 at 15:38
I testedzsh, so it may be that zsh changed behavior between different releases.
â schily
Jun 7 at 15:40
 |Â
show 5 more comments
up vote
2
down vote
It seems that you detected a POSIX deviation in bash that is also a deviation from the historic Bourne Shell. You may call it a bug or a just deviating behavior.
The script you refer to prints
1
2
with all shells except bash in default behavior.
If you call bash --posix, it works correctly.
From a pointer from user Kusalananda it seems that bash by default makes all builtin commands restore their temporary environment at exit and not just for the non-special builtins. Since export is a special builtin, POSIX requires a shell to behave the same as a Bourne Shell from the early 1980s end to keep the environment value.
Since bash does not implement this by default, you get the deviation.
bashin its POSIX mode does the right thing though.
â Kusalananda
Jun 7 at 15:22
Point 30 in Chet's list of differences betweenbash's default mode of operation andbash --posixmay be relevant, possibly.
â Kusalananda
Jun 7 at 15:27
It would be a bug if it didn't work as documented. Herebashbehaves as required by POSIX when in POSIX mode, like when called assh, and works as documented (and some would argue in a less surprising way) otherwise.
â Stéphane Chazelas
Jun 7 at 15:36
Note thatzshbehaves likebashhere, so it's not all shells except bash.
â Stéphane Chazelas
Jun 7 at 15:38
I testedzsh, so it may be that zsh changed behavior between different releases.
â schily
Jun 7 at 15:40
 |Â
show 5 more comments
up vote
2
down vote
up vote
2
down vote
It seems that you detected a POSIX deviation in bash that is also a deviation from the historic Bourne Shell. You may call it a bug or a just deviating behavior.
The script you refer to prints
1
2
with all shells except bash in default behavior.
If you call bash --posix, it works correctly.
From a pointer from user Kusalananda it seems that bash by default makes all builtin commands restore their temporary environment at exit and not just for the non-special builtins. Since export is a special builtin, POSIX requires a shell to behave the same as a Bourne Shell from the early 1980s end to keep the environment value.
Since bash does not implement this by default, you get the deviation.
It seems that you detected a POSIX deviation in bash that is also a deviation from the historic Bourne Shell. You may call it a bug or a just deviating behavior.
The script you refer to prints
1
2
with all shells except bash in default behavior.
If you call bash --posix, it works correctly.
From a pointer from user Kusalananda it seems that bash by default makes all builtin commands restore their temporary environment at exit and not just for the non-special builtins. Since export is a special builtin, POSIX requires a shell to behave the same as a Bourne Shell from the early 1980s end to keep the environment value.
Since bash does not implement this by default, you get the deviation.
edited Jun 7 at 15:42
answered Jun 7 at 15:20
schily
8,61821435
8,61821435
bashin its POSIX mode does the right thing though.
â Kusalananda
Jun 7 at 15:22
Point 30 in Chet's list of differences betweenbash's default mode of operation andbash --posixmay be relevant, possibly.
â Kusalananda
Jun 7 at 15:27
It would be a bug if it didn't work as documented. Herebashbehaves as required by POSIX when in POSIX mode, like when called assh, and works as documented (and some would argue in a less surprising way) otherwise.
â Stéphane Chazelas
Jun 7 at 15:36
Note thatzshbehaves likebashhere, so it's not all shells except bash.
â Stéphane Chazelas
Jun 7 at 15:38
I testedzsh, so it may be that zsh changed behavior between different releases.
â schily
Jun 7 at 15:40
 |Â
show 5 more comments
bashin its POSIX mode does the right thing though.
â Kusalananda
Jun 7 at 15:22
Point 30 in Chet's list of differences betweenbash's default mode of operation andbash --posixmay be relevant, possibly.
â Kusalananda
Jun 7 at 15:27
It would be a bug if it didn't work as documented. Herebashbehaves as required by POSIX when in POSIX mode, like when called assh, and works as documented (and some would argue in a less surprising way) otherwise.
â Stéphane Chazelas
Jun 7 at 15:36
Note thatzshbehaves likebashhere, so it's not all shells except bash.
â Stéphane Chazelas
Jun 7 at 15:38
I testedzsh, so it may be that zsh changed behavior between different releases.
â schily
Jun 7 at 15:40
bash in its POSIX mode does the right thing though.â Kusalananda
Jun 7 at 15:22
bash in its POSIX mode does the right thing though.â Kusalananda
Jun 7 at 15:22
Point 30 in Chet's list of differences between
bash's default mode of operation and bash --posix may be relevant, possibly.â Kusalananda
Jun 7 at 15:27
Point 30 in Chet's list of differences between
bash's default mode of operation and bash --posix may be relevant, possibly.â Kusalananda
Jun 7 at 15:27
It would be a bug if it didn't work as documented. Here
bash behaves as required by POSIX when in POSIX mode, like when called as sh, and works as documented (and some would argue in a less surprising way) otherwise.â Stéphane Chazelas
Jun 7 at 15:36
It would be a bug if it didn't work as documented. Here
bash behaves as required by POSIX when in POSIX mode, like when called as sh, and works as documented (and some would argue in a less surprising way) otherwise.â Stéphane Chazelas
Jun 7 at 15:36
Note that
zsh behaves like bash here, so it's not all shells except bash.â Stéphane Chazelas
Jun 7 at 15:38
Note that
zsh behaves like bash here, so it's not all shells except bash.â Stéphane Chazelas
Jun 7 at 15:38
I tested
zsh, so it may be that zsh changed behavior between different releases.â schily
Jun 7 at 15:40
I tested
zsh, so it may be that zsh changed behavior between different releases.â schily
Jun 7 at 15:40
 |Â
show 5 more comments
up vote
0
down vote
Yes, the behavior is different. The whole description is not so simple.
First: when is it equal?
This code line :
$ var=1; printf "%s" "$var"; var=2 export var; echo " $var"
Will print 1 2 in all (non-csh like) shells except zsh.
jsh : 1 2 # ATT version sh (heirloom).
ash : 1 2
yash : 1 2
dash : 1 2
zsh/sh : 1 2
bash : 1 2
posixbash : 1 2
lksh : 1 2
mksh : 1 2
ksh93 : 1 2
attsh : 1 2
zsh : 1 1
That looks like a mistake of zsh to me. How could be reasonable that exporting a variable does not retain the exported value ?
But that is because the exported variable: var, is the same var that is printed.
Exporting some other var.
If the line is changed to something more similar to what you are asking, with some other varname, like this:
$ var=1; printf "%s" "$var"; var=2 export othervar; echo " $var"
The difference(s) become clear:
jsh : 1 2
dash : 1 2
bash : 1 1
posixbash : 1 2
ksh93 : 1 2
zsh : 1 1
It is clear that bash is different to old sh (Bourne), newer sh (dash), ksh and others (not listed here).
But what is more important is that bash acts differently than bash --posix.
Posix requirement.
Some of the shell builtins (not all) are called "special built-ins":
From: 2.14. Special Built-In Utilities
The following "special built-in" utilities shall be supported in the shell command language.
⦠however, the special built-in utilities described here differ from regular built-in utilities in two respects:
An error in a special built-in utility may cause a shell executing that utility to abort, while an error in a regular built-in utility shall not cause a shell executing that utility to abort. â¦
As described in Simple Commands, variable assignments preceding the invocation of a special built-in utility remain in effect after the built-in completes; this shall not be the case with a regular built-in or other utility.
So, in a simple command: var=2 specialBuiltin the variable var should retain its value after the specialBuiltin has exited. But not all shell implementations follow such rule.
So, this should print 1 hello 2 (as eval is an special builtin):
var=1; printf '%s ' "$var"; var=2 eval printf %s hello; echo " $var"
It does in sh and bash --posix but not in plain bash.
List of special builtins.
In fact, The POSIX list of special builtins is here, the list being:
02 break
03 :
04 .
05 continue
06 eval
07 exec
08 exit
09 export
10 readonly
11 return
12 set
13 shift
14 times
15 trap
16 unset
The number in first column is the value of var used for each test.
We could test all special builtins (except exit, exec and times) with this code:
var=01;
while : ; do var=02 break; done; printf ' %s' "02-$var"; var=01
var=03 : ; printf ' %s' "03-$var"; var=01
echo 'printf " %s" "04-<$var>"' >source-sh
var=04 . source-sh; printf ' %s' "04-$var"; var=01
c=0; while ((c++<1)); do
var=05 continue
done; printf ' %s' "05-$var"; var=01
var=06 eval 'printf " %s" "06-<$var>"'; printf ' %s' "06-$var"; var=01
#( var=07 exec bash -c 'printf " %s" "07-$var"'); var=01
#( var=08 exit; printf ' %s' "08-$var" ); var=01
var=09 export var; printf ' %s' "09-$var"; var=01
var=10 readonly i; printf ' %s' "10-$var"; var=01
varfun() var=11 return; ; varfun; printf ' %s' "11-$var"; var=01
var=12 set -- aa ; printf ' %s' "12-$var"; var=01
var=13 shift; printf ' %s' "13-$var"; var=01
var=15 trap; printf ' %s' "14-$var"; var=01
var=16 unset j; printf ' %s' "15-$var"; var=01
echo
To print this list:
jsh : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
dash : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
bash : 02-01 03-01 04-<04> 04-01 05-01 06-<06> 06-01 09-09 10-01 11-01 12-01 13-01 15-01 16-01
posixbash : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
ksh93 : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
zsh : 02-01 03-01 04-<04> 04-01 05-01 06-<06> 06-01 09-01 10-01 11-01 12-01 13-01 15-01 16-01
As you can see, where posix request that var retain 02 most shells retain it and print 02-02, but not in bash (nor zsh) as they print 02-01. Only in export is bash printing 09-09 and zsh printing 09-01.
So you're saying that in my case bash doesn't keep the value assigned because, since the "export var" command used individually makes a variable visible in the subprocesses and since the bash with the default behavior doesn't take into account special builtins, my bash takes care of exporting the name of the variable that doesn't match with the one assigned, losing the value?
â alessaro
Jun 11 at 7:04
Please do not claim to have a complete list of Bourne-alike shells if you miss important implementations. For an expressive comparison, it is sufficient to list the ones that are most important and/or well maintained. These are: bash dash bosh mksh ksh88 ksh93 zsh I am not sure wether yash should be in that list because of many deviations. zsh also has many deviations and dash cannot be used on a full blown UNIX system since it misses support for multi-byte characters.
â schily
Jun 11 at 9:16
Let me add a note to the heirloom shell. It has been derived from the SunOS Bourne Shell and modified in various undocumented ways. It is not portable and it is unmaintained. In fact, there was no more than 3 months of work from the maintainer. If you like to verify the behavior of the SunOS Bourne Shell, it is better to use the "osh" binary compiled from the bosh sources, since that is very close to the SunOS original and portable.
â schily
Jun 11 at 9:19
@alessaro "Your case" is not theexport varcase. In the later case, the first I cover, bothshandbashact exactly the same. "Your case" is the second I cover.
â Isaac
Jun 11 at 16:25
@schily I am very (very) sorry for your pain. ... But the only thing that matters here is wether "the Bourne shell" prints1 1or1 2, the rest are just opinions.
â Isaac
Jun 11 at 16:33
 |Â
show 4 more comments
up vote
0
down vote
Yes, the behavior is different. The whole description is not so simple.
First: when is it equal?
This code line :
$ var=1; printf "%s" "$var"; var=2 export var; echo " $var"
Will print 1 2 in all (non-csh like) shells except zsh.
jsh : 1 2 # ATT version sh (heirloom).
ash : 1 2
yash : 1 2
dash : 1 2
zsh/sh : 1 2
bash : 1 2
posixbash : 1 2
lksh : 1 2
mksh : 1 2
ksh93 : 1 2
attsh : 1 2
zsh : 1 1
That looks like a mistake of zsh to me. How could be reasonable that exporting a variable does not retain the exported value ?
But that is because the exported variable: var, is the same var that is printed.
Exporting some other var.
If the line is changed to something more similar to what you are asking, with some other varname, like this:
$ var=1; printf "%s" "$var"; var=2 export othervar; echo " $var"
The difference(s) become clear:
jsh : 1 2
dash : 1 2
bash : 1 1
posixbash : 1 2
ksh93 : 1 2
zsh : 1 1
It is clear that bash is different to old sh (Bourne), newer sh (dash), ksh and others (not listed here).
But what is more important is that bash acts differently than bash --posix.
Posix requirement.
Some of the shell builtins (not all) are called "special built-ins":
From: 2.14. Special Built-In Utilities
The following "special built-in" utilities shall be supported in the shell command language.
⦠however, the special built-in utilities described here differ from regular built-in utilities in two respects:
An error in a special built-in utility may cause a shell executing that utility to abort, while an error in a regular built-in utility shall not cause a shell executing that utility to abort. â¦
As described in Simple Commands, variable assignments preceding the invocation of a special built-in utility remain in effect after the built-in completes; this shall not be the case with a regular built-in or other utility.
So, in a simple command: var=2 specialBuiltin the variable var should retain its value after the specialBuiltin has exited. But not all shell implementations follow such rule.
So, this should print 1 hello 2 (as eval is an special builtin):
var=1; printf '%s ' "$var"; var=2 eval printf %s hello; echo " $var"
It does in sh and bash --posix but not in plain bash.
List of special builtins.
In fact, The POSIX list of special builtins is here, the list being:
02 break
03 :
04 .
05 continue
06 eval
07 exec
08 exit
09 export
10 readonly
11 return
12 set
13 shift
14 times
15 trap
16 unset
The number in first column is the value of var used for each test.
We could test all special builtins (except exit, exec and times) with this code:
var=01;
while : ; do var=02 break; done; printf ' %s' "02-$var"; var=01
var=03 : ; printf ' %s' "03-$var"; var=01
echo 'printf " %s" "04-<$var>"' >source-sh
var=04 . source-sh; printf ' %s' "04-$var"; var=01
c=0; while ((c++<1)); do
var=05 continue
done; printf ' %s' "05-$var"; var=01
var=06 eval 'printf " %s" "06-<$var>"'; printf ' %s' "06-$var"; var=01
#( var=07 exec bash -c 'printf " %s" "07-$var"'); var=01
#( var=08 exit; printf ' %s' "08-$var" ); var=01
var=09 export var; printf ' %s' "09-$var"; var=01
var=10 readonly i; printf ' %s' "10-$var"; var=01
varfun() var=11 return; ; varfun; printf ' %s' "11-$var"; var=01
var=12 set -- aa ; printf ' %s' "12-$var"; var=01
var=13 shift; printf ' %s' "13-$var"; var=01
var=15 trap; printf ' %s' "14-$var"; var=01
var=16 unset j; printf ' %s' "15-$var"; var=01
echo
To print this list:
jsh : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
dash : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
bash : 02-01 03-01 04-<04> 04-01 05-01 06-<06> 06-01 09-09 10-01 11-01 12-01 13-01 15-01 16-01
posixbash : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
ksh93 : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
zsh : 02-01 03-01 04-<04> 04-01 05-01 06-<06> 06-01 09-01 10-01 11-01 12-01 13-01 15-01 16-01
As you can see, where posix request that var retain 02 most shells retain it and print 02-02, but not in bash (nor zsh) as they print 02-01. Only in export is bash printing 09-09 and zsh printing 09-01.
So you're saying that in my case bash doesn't keep the value assigned because, since the "export var" command used individually makes a variable visible in the subprocesses and since the bash with the default behavior doesn't take into account special builtins, my bash takes care of exporting the name of the variable that doesn't match with the one assigned, losing the value?
â alessaro
Jun 11 at 7:04
Please do not claim to have a complete list of Bourne-alike shells if you miss important implementations. For an expressive comparison, it is sufficient to list the ones that are most important and/or well maintained. These are: bash dash bosh mksh ksh88 ksh93 zsh I am not sure wether yash should be in that list because of many deviations. zsh also has many deviations and dash cannot be used on a full blown UNIX system since it misses support for multi-byte characters.
â schily
Jun 11 at 9:16
Let me add a note to the heirloom shell. It has been derived from the SunOS Bourne Shell and modified in various undocumented ways. It is not portable and it is unmaintained. In fact, there was no more than 3 months of work from the maintainer. If you like to verify the behavior of the SunOS Bourne Shell, it is better to use the "osh" binary compiled from the bosh sources, since that is very close to the SunOS original and portable.
â schily
Jun 11 at 9:19
@alessaro "Your case" is not theexport varcase. In the later case, the first I cover, bothshandbashact exactly the same. "Your case" is the second I cover.
â Isaac
Jun 11 at 16:25
@schily I am very (very) sorry for your pain. ... But the only thing that matters here is wether "the Bourne shell" prints1 1or1 2, the rest are just opinions.
â Isaac
Jun 11 at 16:33
 |Â
show 4 more comments
up vote
0
down vote
up vote
0
down vote
Yes, the behavior is different. The whole description is not so simple.
First: when is it equal?
This code line :
$ var=1; printf "%s" "$var"; var=2 export var; echo " $var"
Will print 1 2 in all (non-csh like) shells except zsh.
jsh : 1 2 # ATT version sh (heirloom).
ash : 1 2
yash : 1 2
dash : 1 2
zsh/sh : 1 2
bash : 1 2
posixbash : 1 2
lksh : 1 2
mksh : 1 2
ksh93 : 1 2
attsh : 1 2
zsh : 1 1
That looks like a mistake of zsh to me. How could be reasonable that exporting a variable does not retain the exported value ?
But that is because the exported variable: var, is the same var that is printed.
Exporting some other var.
If the line is changed to something more similar to what you are asking, with some other varname, like this:
$ var=1; printf "%s" "$var"; var=2 export othervar; echo " $var"
The difference(s) become clear:
jsh : 1 2
dash : 1 2
bash : 1 1
posixbash : 1 2
ksh93 : 1 2
zsh : 1 1
It is clear that bash is different to old sh (Bourne), newer sh (dash), ksh and others (not listed here).
But what is more important is that bash acts differently than bash --posix.
Posix requirement.
Some of the shell builtins (not all) are called "special built-ins":
From: 2.14. Special Built-In Utilities
The following "special built-in" utilities shall be supported in the shell command language.
⦠however, the special built-in utilities described here differ from regular built-in utilities in two respects:
An error in a special built-in utility may cause a shell executing that utility to abort, while an error in a regular built-in utility shall not cause a shell executing that utility to abort. â¦
As described in Simple Commands, variable assignments preceding the invocation of a special built-in utility remain in effect after the built-in completes; this shall not be the case with a regular built-in or other utility.
So, in a simple command: var=2 specialBuiltin the variable var should retain its value after the specialBuiltin has exited. But not all shell implementations follow such rule.
So, this should print 1 hello 2 (as eval is an special builtin):
var=1; printf '%s ' "$var"; var=2 eval printf %s hello; echo " $var"
It does in sh and bash --posix but not in plain bash.
List of special builtins.
In fact, The POSIX list of special builtins is here, the list being:
02 break
03 :
04 .
05 continue
06 eval
07 exec
08 exit
09 export
10 readonly
11 return
12 set
13 shift
14 times
15 trap
16 unset
The number in first column is the value of var used for each test.
We could test all special builtins (except exit, exec and times) with this code:
var=01;
while : ; do var=02 break; done; printf ' %s' "02-$var"; var=01
var=03 : ; printf ' %s' "03-$var"; var=01
echo 'printf " %s" "04-<$var>"' >source-sh
var=04 . source-sh; printf ' %s' "04-$var"; var=01
c=0; while ((c++<1)); do
var=05 continue
done; printf ' %s' "05-$var"; var=01
var=06 eval 'printf " %s" "06-<$var>"'; printf ' %s' "06-$var"; var=01
#( var=07 exec bash -c 'printf " %s" "07-$var"'); var=01
#( var=08 exit; printf ' %s' "08-$var" ); var=01
var=09 export var; printf ' %s' "09-$var"; var=01
var=10 readonly i; printf ' %s' "10-$var"; var=01
varfun() var=11 return; ; varfun; printf ' %s' "11-$var"; var=01
var=12 set -- aa ; printf ' %s' "12-$var"; var=01
var=13 shift; printf ' %s' "13-$var"; var=01
var=15 trap; printf ' %s' "14-$var"; var=01
var=16 unset j; printf ' %s' "15-$var"; var=01
echo
To print this list:
jsh : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
dash : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
bash : 02-01 03-01 04-<04> 04-01 05-01 06-<06> 06-01 09-09 10-01 11-01 12-01 13-01 15-01 16-01
posixbash : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
ksh93 : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
zsh : 02-01 03-01 04-<04> 04-01 05-01 06-<06> 06-01 09-01 10-01 11-01 12-01 13-01 15-01 16-01
As you can see, where posix request that var retain 02 most shells retain it and print 02-02, but not in bash (nor zsh) as they print 02-01. Only in export is bash printing 09-09 and zsh printing 09-01.
Yes, the behavior is different. The whole description is not so simple.
First: when is it equal?
This code line :
$ var=1; printf "%s" "$var"; var=2 export var; echo " $var"
Will print 1 2 in all (non-csh like) shells except zsh.
jsh : 1 2 # ATT version sh (heirloom).
ash : 1 2
yash : 1 2
dash : 1 2
zsh/sh : 1 2
bash : 1 2
posixbash : 1 2
lksh : 1 2
mksh : 1 2
ksh93 : 1 2
attsh : 1 2
zsh : 1 1
That looks like a mistake of zsh to me. How could be reasonable that exporting a variable does not retain the exported value ?
But that is because the exported variable: var, is the same var that is printed.
Exporting some other var.
If the line is changed to something more similar to what you are asking, with some other varname, like this:
$ var=1; printf "%s" "$var"; var=2 export othervar; echo " $var"
The difference(s) become clear:
jsh : 1 2
dash : 1 2
bash : 1 1
posixbash : 1 2
ksh93 : 1 2
zsh : 1 1
It is clear that bash is different to old sh (Bourne), newer sh (dash), ksh and others (not listed here).
But what is more important is that bash acts differently than bash --posix.
Posix requirement.
Some of the shell builtins (not all) are called "special built-ins":
From: 2.14. Special Built-In Utilities
The following "special built-in" utilities shall be supported in the shell command language.
⦠however, the special built-in utilities described here differ from regular built-in utilities in two respects:
An error in a special built-in utility may cause a shell executing that utility to abort, while an error in a regular built-in utility shall not cause a shell executing that utility to abort. â¦
As described in Simple Commands, variable assignments preceding the invocation of a special built-in utility remain in effect after the built-in completes; this shall not be the case with a regular built-in or other utility.
So, in a simple command: var=2 specialBuiltin the variable var should retain its value after the specialBuiltin has exited. But not all shell implementations follow such rule.
So, this should print 1 hello 2 (as eval is an special builtin):
var=1; printf '%s ' "$var"; var=2 eval printf %s hello; echo " $var"
It does in sh and bash --posix but not in plain bash.
List of special builtins.
In fact, The POSIX list of special builtins is here, the list being:
02 break
03 :
04 .
05 continue
06 eval
07 exec
08 exit
09 export
10 readonly
11 return
12 set
13 shift
14 times
15 trap
16 unset
The number in first column is the value of var used for each test.
We could test all special builtins (except exit, exec and times) with this code:
var=01;
while : ; do var=02 break; done; printf ' %s' "02-$var"; var=01
var=03 : ; printf ' %s' "03-$var"; var=01
echo 'printf " %s" "04-<$var>"' >source-sh
var=04 . source-sh; printf ' %s' "04-$var"; var=01
c=0; while ((c++<1)); do
var=05 continue
done; printf ' %s' "05-$var"; var=01
var=06 eval 'printf " %s" "06-<$var>"'; printf ' %s' "06-$var"; var=01
#( var=07 exec bash -c 'printf " %s" "07-$var"'); var=01
#( var=08 exit; printf ' %s' "08-$var" ); var=01
var=09 export var; printf ' %s' "09-$var"; var=01
var=10 readonly i; printf ' %s' "10-$var"; var=01
varfun() var=11 return; ; varfun; printf ' %s' "11-$var"; var=01
var=12 set -- aa ; printf ' %s' "12-$var"; var=01
var=13 shift; printf ' %s' "13-$var"; var=01
var=15 trap; printf ' %s' "14-$var"; var=01
var=16 unset j; printf ' %s' "15-$var"; var=01
echo
To print this list:
jsh : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
dash : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
bash : 02-01 03-01 04-<04> 04-01 05-01 06-<06> 06-01 09-09 10-01 11-01 12-01 13-01 15-01 16-01
posixbash : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
ksh93 : 02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
zsh : 02-01 03-01 04-<04> 04-01 05-01 06-<06> 06-01 09-01 10-01 11-01 12-01 13-01 15-01 16-01
As you can see, where posix request that var retain 02 most shells retain it and print 02-02, but not in bash (nor zsh) as they print 02-01. Only in export is bash printing 09-09 and zsh printing 09-01.
answered Jun 10 at 5:10
Isaac
6,3041632
6,3041632
So you're saying that in my case bash doesn't keep the value assigned because, since the "export var" command used individually makes a variable visible in the subprocesses and since the bash with the default behavior doesn't take into account special builtins, my bash takes care of exporting the name of the variable that doesn't match with the one assigned, losing the value?
â alessaro
Jun 11 at 7:04
Please do not claim to have a complete list of Bourne-alike shells if you miss important implementations. For an expressive comparison, it is sufficient to list the ones that are most important and/or well maintained. These are: bash dash bosh mksh ksh88 ksh93 zsh I am not sure wether yash should be in that list because of many deviations. zsh also has many deviations and dash cannot be used on a full blown UNIX system since it misses support for multi-byte characters.
â schily
Jun 11 at 9:16
Let me add a note to the heirloom shell. It has been derived from the SunOS Bourne Shell and modified in various undocumented ways. It is not portable and it is unmaintained. In fact, there was no more than 3 months of work from the maintainer. If you like to verify the behavior of the SunOS Bourne Shell, it is better to use the "osh" binary compiled from the bosh sources, since that is very close to the SunOS original and portable.
â schily
Jun 11 at 9:19
@alessaro "Your case" is not theexport varcase. In the later case, the first I cover, bothshandbashact exactly the same. "Your case" is the second I cover.
â Isaac
Jun 11 at 16:25
@schily I am very (very) sorry for your pain. ... But the only thing that matters here is wether "the Bourne shell" prints1 1or1 2, the rest are just opinions.
â Isaac
Jun 11 at 16:33
 |Â
show 4 more comments
So you're saying that in my case bash doesn't keep the value assigned because, since the "export var" command used individually makes a variable visible in the subprocesses and since the bash with the default behavior doesn't take into account special builtins, my bash takes care of exporting the name of the variable that doesn't match with the one assigned, losing the value?
â alessaro
Jun 11 at 7:04
Please do not claim to have a complete list of Bourne-alike shells if you miss important implementations. For an expressive comparison, it is sufficient to list the ones that are most important and/or well maintained. These are: bash dash bosh mksh ksh88 ksh93 zsh I am not sure wether yash should be in that list because of many deviations. zsh also has many deviations and dash cannot be used on a full blown UNIX system since it misses support for multi-byte characters.
â schily
Jun 11 at 9:16
Let me add a note to the heirloom shell. It has been derived from the SunOS Bourne Shell and modified in various undocumented ways. It is not portable and it is unmaintained. In fact, there was no more than 3 months of work from the maintainer. If you like to verify the behavior of the SunOS Bourne Shell, it is better to use the "osh" binary compiled from the bosh sources, since that is very close to the SunOS original and portable.
â schily
Jun 11 at 9:19
@alessaro "Your case" is not theexport varcase. In the later case, the first I cover, bothshandbashact exactly the same. "Your case" is the second I cover.
â Isaac
Jun 11 at 16:25
@schily I am very (very) sorry for your pain. ... But the only thing that matters here is wether "the Bourne shell" prints1 1or1 2, the rest are just opinions.
â Isaac
Jun 11 at 16:33
So you're saying that in my case bash doesn't keep the value assigned because, since the "export var" command used individually makes a variable visible in the subprocesses and since the bash with the default behavior doesn't take into account special builtins, my bash takes care of exporting the name of the variable that doesn't match with the one assigned, losing the value?
â alessaro
Jun 11 at 7:04
So you're saying that in my case bash doesn't keep the value assigned because, since the "export var" command used individually makes a variable visible in the subprocesses and since the bash with the default behavior doesn't take into account special builtins, my bash takes care of exporting the name of the variable that doesn't match with the one assigned, losing the value?
â alessaro
Jun 11 at 7:04
Please do not claim to have a complete list of Bourne-alike shells if you miss important implementations. For an expressive comparison, it is sufficient to list the ones that are most important and/or well maintained. These are: bash dash bosh mksh ksh88 ksh93 zsh I am not sure wether yash should be in that list because of many deviations. zsh also has many deviations and dash cannot be used on a full blown UNIX system since it misses support for multi-byte characters.
â schily
Jun 11 at 9:16
Please do not claim to have a complete list of Bourne-alike shells if you miss important implementations. For an expressive comparison, it is sufficient to list the ones that are most important and/or well maintained. These are: bash dash bosh mksh ksh88 ksh93 zsh I am not sure wether yash should be in that list because of many deviations. zsh also has many deviations and dash cannot be used on a full blown UNIX system since it misses support for multi-byte characters.
â schily
Jun 11 at 9:16
Let me add a note to the heirloom shell. It has been derived from the SunOS Bourne Shell and modified in various undocumented ways. It is not portable and it is unmaintained. In fact, there was no more than 3 months of work from the maintainer. If you like to verify the behavior of the SunOS Bourne Shell, it is better to use the "osh" binary compiled from the bosh sources, since that is very close to the SunOS original and portable.
â schily
Jun 11 at 9:19
Let me add a note to the heirloom shell. It has been derived from the SunOS Bourne Shell and modified in various undocumented ways. It is not portable and it is unmaintained. In fact, there was no more than 3 months of work from the maintainer. If you like to verify the behavior of the SunOS Bourne Shell, it is better to use the "osh" binary compiled from the bosh sources, since that is very close to the SunOS original and portable.
â schily
Jun 11 at 9:19
@alessaro "Your case" is not the
export var case. In the later case, the first I cover, both sh and bash act exactly the same. "Your case" is the second I cover.â Isaac
Jun 11 at 16:25
@alessaro "Your case" is not the
export var case. In the later case, the first I cover, both sh and bash act exactly the same. "Your case" is the second I cover.â Isaac
Jun 11 at 16:25
@schily I am very (very) sorry for your pain. ... But the only thing that matters here is wether "the Bourne shell" prints
1 1 or 1 2, the rest are just opinions.â Isaac
Jun 11 at 16:33
@schily I am very (very) sorry for your pain. ... But the only thing that matters here is wether "the Bourne shell" prints
1 1 or 1 2, the rest are just opinions.â Isaac
Jun 11 at 16:33
 |Â
show 4 more comments
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f448450%2fis-the-export-command-behaviour-different-in-sh-and-in-bash%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
You're right about your edit, looks like I messed up my tests, I'll update my answer.
â Stéphane Chazelas
Jun 8 at 11:42