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

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
6
down vote

favorite
3












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.







share|improve this question





















  • 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














up vote
6
down vote

favorite
3












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.







share|improve this question





















  • 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












up vote
6
down vote

favorite
3









up vote
6
down vote

favorite
3






3





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.







share|improve this question













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.









share|improve this question












share|improve this question




share|improve this question








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
















  • 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










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.






share|improve this answer























  • 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











  • 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










  • I tested zsh, so it may be that zsh changed behavior between different releases.
    – schily
    Jun 7 at 15:40


















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:



  1. 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. …


  2. 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.






share|improve this answer





















  • 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 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










Your Answer







StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















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






























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.






share|improve this answer























  • 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











  • 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










  • I tested zsh, so it may be that zsh changed behavior between different releases.
    – schily
    Jun 7 at 15:40















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.






share|improve this answer























  • 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











  • 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










  • I tested zsh, so it may be that zsh changed behavior between different releases.
    – schily
    Jun 7 at 15:40













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.






share|improve this answer















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.







share|improve this answer















share|improve this answer



share|improve this answer








edited Jun 7 at 15:42


























answered Jun 7 at 15:20









schily

8,61821435




8,61821435











  • 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











  • 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










  • I tested zsh, 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










  • 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











  • 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
















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













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:



  1. 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. …


  2. 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.






share|improve this answer





















  • 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 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














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:



  1. 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. …


  2. 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.






share|improve this answer





















  • 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 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












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:



  1. 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. …


  2. 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.






share|improve this answer













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:



  1. 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. …


  2. 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.







share|improve this answer













share|improve this answer



share|improve this answer











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 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
















  • 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 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















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












 

draft saved


draft discarded


























 


draft saved


draft discarded














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













































































Popular posts from this blog

Peggy Mitchell

Palaiologos

The Forum (Inglewood, California)