Some examples of scoping in bash.    Because I forget.   This makes it clear.


* Print shell verion
#+begin_src bash :exports both :results output :session
date
echo SHELL is $SHELL
echo BASH_VERSION is $BASH_VERSION
#+end_src

#+RESULTS:
: Thu Nov 17 03:49:42 AM EST 2022
: SHELL is /bin/bash
: BASH_VERSION is 5.1.16(1)-release

# echo SHELL is $SHELL
# echo BASH_VERSION is $BASH_VERSION

* Setup - Don't ask about resetting the session                    :noexport:

  Pay no attention to that man behind the curtain.

  This is emacs lisp foo that turn of prompting when killing the
  buffer running the shell.

#+BEGIN_SRC elisp
  (setq kill-buffer-query-functions
    (remq 'process-kill-buffer-query-function
           kill-buffer-query-functions))
#+END_SRC

#+RESULTS:

* Reset the session :results output                                :noexport:

  Kill the TEST session.   Variables, PID should reset.

  https://emacs.stackexchange.com/questions/5293/how-to-force-an-org-babel-session-to-reset-or-initialize
  #+begin_src bash :exports both :results output :session  (if (get-buffer "TEST") (if (kill-buffer "TEST") (print "TEST") (print "TEST")) (print "TEST"))

  PS1="$ "
  date
  echo TEST session killed
  echo PID is $$

  [[ -v SET_IN_FIRST_BLOCK ]] && \
    echo SET_IN_FIRST_BLOCK is $SET_IN_FIRST_BLOCK || \
        echo SET_IN_FIRST_BLOCK is not defined
  #+end_src

  #+RESULTS:
  :
  : gmj@mx:$ Thu Nov 17 02:38:41 AM EST 2022
  : TEST session killed
  : PID is 88632
  : gmj@mx:$ > > SET_IN_FIRST_BLOCK is not defined



* Test/demonstrate scoping of variables in bash functions
** Code
#+begin_src bash :exports both :results output :session
date
echo

FOO=FOO-set-outside-functon
function baz { echo inside baz FOO is $FOO; FOO=FOO-set-inside-inside; }
baz
echo FOO is $FOO

#+end_src
** Conclusions
   Bash variables are simply global.


#+RESULTS:
: Thu Nov 17 03:44:59 AM EST 2022
: inside baz FOO is FOO-set-outside-functon
: FOO is FOO-set-inside-inside


* Test/demonstrate scoping of variables in bash functions using subprocesses
** Code
#+begin_src bash :exports both :results output :session
date
echo

FOO=FOO-set-outside-functon
function baz { (echo inside baz FOO is $FOO; FOO=FOO-set-inside-inside;) }
echo
baz
echo
echo FOO is $FOO

#+end_src

#+RESULTS:
: Thu Nov 17 03:52:35 AM EST 2022
:
:
: inside baz FOO is FOO-set-outside-functon
:
: FOO is FOO-set-outside-functon

** Conclusions

   Running in a sub-shell, the function receives copies (via fork(2))
   of global variables, but then they, and any variables defined in
   the function remain local to the function.  This is better.   Only
   downside is creation of a process  ... heavy-weight operation.  OK
   if not used in heavy processing


#+RESULTS:
: Thu Nov 17 03:44:59 AM EST 2022
: inside baz FOO is FOO-set-outside-functon
: FOO is FOO-set-inside-inside




* Test/demonstrate scoping of EXPORT variables in bash
** Code
#+begin_src bash :exports both :results output :session
date


# set FOO to known state
unset FOO
FOO=bar

# expand FOO in "normal" function
function f { echo In f, FOO is $FOO; }
f

# expand FOO in "subprocess" function
function g { (echo In g, FOO in subprocess is $FOO) }
g

# expand FOO in a separate command/script
cat > h <<'EOF'
#! /bin/bash
set -u
[[ -v FOO ]] && echo in h FOO is $FOO || echo in h FOO is not defined
EOF
chmod +x h
./h
# not defined

# export it, now seen via ENV
export FOO
./h

#+end_src

#+RESULTS:
: Thu Nov 17 04:14:03 AM EST 2022
: In f, FOO is bar
: In g, FOO in subprocess is bar
: in h FOO is not defined
: in h FOO is bar

** Conclusions

   EXPORTED variables are visible to other commands.




* Raw stuff - move up
# #
# # Exporting variables to subshells
# #
# $ export -p | grep FOO
# $ # FOO is not exported

# $ FOO=bar
# $ export -p | grep FOO
# $ # FOO is still not exported

# $ export FOO=baz
# $ export -p | grep FOO
# declare -x FOO="baz"
# # Q: but as we see below, non-exported variables are
# #    inherited by subproceses (probably as a conseuqence
# #    of fork(2).  When are exports neeed?


# #
# # Testing scoping of varibles in subshells
# #

# # Q: are variable in a sub-shell local to that shell?
# unset FOO
# FOO=bar
# function blort {
#     (
#         echo FOO inside blort is $FOO;
#         FOO=foo-inside;
#         echo FOO inside blort is $FOO after setting
#     )
# }
# blort
# echo FOO outside blort after call to baz is $FOO
# # A: yes. FOO did not change outside the function.
# #
# # Commentary.  This seems like a "safe" way to
# #   lmit namespace pollution and side-effects in bash,
# #   as long as you don't find the fork/exec overhead.

# #
# # Figure how EXPORT works/when needed.
# #

# # inital state: FOO unbound
# unset FOO
# set -u
# echo $FOO
# #bash: FOO: unbound variable

# # FOO set to bar
# FOO=bar

# #
# function f { echo FOO is $FOO; }
# f
# #FOO is bar
# function g { (echo FOO in subprocess is$FOO) }
# g
# #FOO in subprocess isbar
# FOO=foo
# f
# #FOO is foo
# g
# #FOO in subprocess isfoo
# cat <<EOF
# #! /bin/bash
# set -u
# echo in h FOO is $FOO
# EOF
# chmod +x h
# unalias h
# ./h
# #./h: line 3: FOO: unbound variable

# export FOO=qux
# ./h
# # in h FOO is qux
