Differentiating between running and being sourced in a bash shell script?

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












19















Either what I'm asking here is extremely unorthodox/unconventional/risky, or my Google-fu skills just aren't up to snuff...



In a bash shell script, is there any easy of way of telling if it is getting sourced by another shell script, or is it being run by itself? In other words, is it possible to differentiate between the following two behaviors?



# from another shell script
source myScript.sh

# from command prompt, or another shell script
./myScript.sh


What I'm thinking of doing is to create an utilities-like shell script containing bash functions that can be made available when sourced. When this script is being run by itself though, I'll like it to perform certain operations, based on the defined functions too. Is there some kind of an environment variable that this shell script can pick up on, e.g.



some_function() 
# ...

if [ -z "$IS_SOURCED" ]; then
some_function;
fi


Preferably, I'm looking for a solution that doesn't require the caller script to set any flag variables.



edit: I know the difference between sourcing and and running the script, what I'm trying to find out here if it's possible to tell the difference in the script that is being used (in both ways).










share|improve this question



















  • 1





    possible duplicate of running script with ". " and with "source "

    – cuonglm
    Jul 6 '15 at 2:25











  • @cuonglm edited my question, I know the differences between the both but I'm wondering if I can programmatically make the shell script tell the difference as well.

    – h.j.k.
    Jul 6 '15 at 2:31






  • 4





    @cuonglm: Not a duplicate. He's not asking about the . command at all, but about detecting whether a script has been sourced or run normally (i.e. in a subshell).

    – Jander
    Jul 6 '15 at 6:21











  • Very good answers on same question at stack overflow: stackoverflow.com/a/28776166/96944

    – Jannie Theunissen
    Feb 6 '18 at 6:49















19















Either what I'm asking here is extremely unorthodox/unconventional/risky, or my Google-fu skills just aren't up to snuff...



In a bash shell script, is there any easy of way of telling if it is getting sourced by another shell script, or is it being run by itself? In other words, is it possible to differentiate between the following two behaviors?



# from another shell script
source myScript.sh

# from command prompt, or another shell script
./myScript.sh


What I'm thinking of doing is to create an utilities-like shell script containing bash functions that can be made available when sourced. When this script is being run by itself though, I'll like it to perform certain operations, based on the defined functions too. Is there some kind of an environment variable that this shell script can pick up on, e.g.



some_function() 
# ...

if [ -z "$IS_SOURCED" ]; then
some_function;
fi


Preferably, I'm looking for a solution that doesn't require the caller script to set any flag variables.



edit: I know the difference between sourcing and and running the script, what I'm trying to find out here if it's possible to tell the difference in the script that is being used (in both ways).










share|improve this question



















  • 1





    possible duplicate of running script with ". " and with "source "

    – cuonglm
    Jul 6 '15 at 2:25











  • @cuonglm edited my question, I know the differences between the both but I'm wondering if I can programmatically make the shell script tell the difference as well.

    – h.j.k.
    Jul 6 '15 at 2:31






  • 4





    @cuonglm: Not a duplicate. He's not asking about the . command at all, but about detecting whether a script has been sourced or run normally (i.e. in a subshell).

    – Jander
    Jul 6 '15 at 6:21











  • Very good answers on same question at stack overflow: stackoverflow.com/a/28776166/96944

    – Jannie Theunissen
    Feb 6 '18 at 6:49













19












19








19


5






Either what I'm asking here is extremely unorthodox/unconventional/risky, or my Google-fu skills just aren't up to snuff...



In a bash shell script, is there any easy of way of telling if it is getting sourced by another shell script, or is it being run by itself? In other words, is it possible to differentiate between the following two behaviors?



# from another shell script
source myScript.sh

# from command prompt, or another shell script
./myScript.sh


What I'm thinking of doing is to create an utilities-like shell script containing bash functions that can be made available when sourced. When this script is being run by itself though, I'll like it to perform certain operations, based on the defined functions too. Is there some kind of an environment variable that this shell script can pick up on, e.g.



some_function() 
# ...

if [ -z "$IS_SOURCED" ]; then
some_function;
fi


Preferably, I'm looking for a solution that doesn't require the caller script to set any flag variables.



edit: I know the difference between sourcing and and running the script, what I'm trying to find out here if it's possible to tell the difference in the script that is being used (in both ways).










share|improve this question
















Either what I'm asking here is extremely unorthodox/unconventional/risky, or my Google-fu skills just aren't up to snuff...



In a bash shell script, is there any easy of way of telling if it is getting sourced by another shell script, or is it being run by itself? In other words, is it possible to differentiate between the following two behaviors?



# from another shell script
source myScript.sh

# from command prompt, or another shell script
./myScript.sh


What I'm thinking of doing is to create an utilities-like shell script containing bash functions that can be made available when sourced. When this script is being run by itself though, I'll like it to perform certain operations, based on the defined functions too. Is there some kind of an environment variable that this shell script can pick up on, e.g.



some_function() 
# ...

if [ -z "$IS_SOURCED" ]; then
some_function;
fi


Preferably, I'm looking for a solution that doesn't require the caller script to set any flag variables.



edit: I know the difference between sourcing and and running the script, what I'm trying to find out here if it's possible to tell the difference in the script that is being used (in both ways).







bash shell-script






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jul 6 '15 at 2:30







h.j.k.

















asked Jul 6 '15 at 2:23









h.j.k.h.j.k.

825719




825719







  • 1





    possible duplicate of running script with ". " and with "source "

    – cuonglm
    Jul 6 '15 at 2:25











  • @cuonglm edited my question, I know the differences between the both but I'm wondering if I can programmatically make the shell script tell the difference as well.

    – h.j.k.
    Jul 6 '15 at 2:31






  • 4





    @cuonglm: Not a duplicate. He's not asking about the . command at all, but about detecting whether a script has been sourced or run normally (i.e. in a subshell).

    – Jander
    Jul 6 '15 at 6:21











  • Very good answers on same question at stack overflow: stackoverflow.com/a/28776166/96944

    – Jannie Theunissen
    Feb 6 '18 at 6:49












  • 1





    possible duplicate of running script with ". " and with "source "

    – cuonglm
    Jul 6 '15 at 2:25











  • @cuonglm edited my question, I know the differences between the both but I'm wondering if I can programmatically make the shell script tell the difference as well.

    – h.j.k.
    Jul 6 '15 at 2:31






  • 4





    @cuonglm: Not a duplicate. He's not asking about the . command at all, but about detecting whether a script has been sourced or run normally (i.e. in a subshell).

    – Jander
    Jul 6 '15 at 6:21











  • Very good answers on same question at stack overflow: stackoverflow.com/a/28776166/96944

    – Jannie Theunissen
    Feb 6 '18 at 6:49







1




1





possible duplicate of running script with ". " and with "source "

– cuonglm
Jul 6 '15 at 2:25





possible duplicate of running script with ". " and with "source "

– cuonglm
Jul 6 '15 at 2:25













@cuonglm edited my question, I know the differences between the both but I'm wondering if I can programmatically make the shell script tell the difference as well.

– h.j.k.
Jul 6 '15 at 2:31





@cuonglm edited my question, I know the differences between the both but I'm wondering if I can programmatically make the shell script tell the difference as well.

– h.j.k.
Jul 6 '15 at 2:31




4




4





@cuonglm: Not a duplicate. He's not asking about the . command at all, but about detecting whether a script has been sourced or run normally (i.e. in a subshell).

– Jander
Jul 6 '15 at 6:21





@cuonglm: Not a duplicate. He's not asking about the . command at all, but about detecting whether a script has been sourced or run normally (i.e. in a subshell).

– Jander
Jul 6 '15 at 6:21













Very good answers on same question at stack overflow: stackoverflow.com/a/28776166/96944

– Jannie Theunissen
Feb 6 '18 at 6:49





Very good answers on same question at stack overflow: stackoverflow.com/a/28776166/96944

– Jannie Theunissen
Feb 6 '18 at 6:49










4 Answers
4






active

oldest

votes


















17














Yes - the $0 variable gives the name of the script as it was run:



$ cat example.sh
#!/bin/bash
script_name=$( basename $0#- ) #- needed if sourced no path
this_script=$( basename $BASH_SOURCE )
if [[ $script_name = $this_script ]] ; then
echo "running me directly"
else
echo "sourced from $script_name"
fi

$ cat example2.sh
#!/bin/bash
. ./example.sh


Which runs like:



$ ./example.sh
running me directly
$ ./example2.sh
example.sh sourced from example2.sh


That doesn't cater for being source from an interactive shell, but you get this idea (I hope).



Updated to include BASH_SOURCE - thanks h.j.k






share|improve this answer

























  • Close enough. :) Small hindrance that I'll need to specify the script's name at least, but I'll take this answer if there are no other viable solutions...

    – h.j.k.
    Jul 6 '15 at 2:40


















6














Combining @DarkHeart's answer with the environment variable BASH_SOURCE seems to do the trick:





$ head example*.sh
==> example2.sh <==
#!/bin/bash
. ./example.sh

==> example.sh <==
#!/bin/bash
if [ "$(basename $0)" = "$(basename $BASH_SOURCE)" ]; then
echo "running directly"
else
echo "sourced from $0"
fi
$ ./example2.sh
sourced from ./example2.sh
$ ./example.sh
running directly


edit Seems to be a simpler solution still if I were to just count the number of elements in BASH_SOURCE's array:



if [ $#BASH_SOURCE[@] -eq 1 ]; then echo "running directly"; else echo "sourced from $0"; fi





share|improve this answer




















  • 1





    Looks like we found the 'bash_source' variable at the same time. :)

    – DarkHeart
    Jul 6 '15 at 2:58











  • @DarkHeart I've added onto my answer the usage of counting the array size too... thanks for hinting me on this path! :D

    – h.j.k.
    Jul 6 '15 at 3:07


















1














I just created the same kind of library script that works alot like BusyBox. In it, I use the following function to test if it is being sourced...



function isSourced () 
[[ "$FUNCNAME[1]" == "source" ]] && return 0
return 1



The Bash-maintained FUNCNAME array is essentially a function call stack. $FUNCNAME (or $FUNCNAME[0]) is the name of the currently executing function. $FUNCNAME[1] is the name of the function that called it, and so on.



The topmost item is a special value for the script itself. It will contain...



  • the word "source" if the script is being sourced

  • the word "main" if the script is being executed AND the test is being done from within a function

  • ""(null) if the script is being executed AND the test is being done outside of any function, that is... at the level of the script itself.

The function above actually only works when called at the script level (which is all I needed). It would fail if called from inside another function because the array item number would be wrong. To make it work anywhere requires finding the top of the stack and testing that value, which is more complicated.



If you need that, you can get the array item number of the "top of the stack" with...



 local _top_of_stack=$(( $#FUNCNAME[@] - 1 ))


$#FUNCNAME[@] is the number of items in the array. As a zero-based array, we subtract 1 to get the last item#.



These three functions are used together to produce a function stack trace similar to Python's and they may give you a better idea how all this works...



function inspFnStack () $i $T$(inspFnStackItem $i)n"
T+=" "
((--i))
done
#
printf "$_textn"
#
return 0


function inspFnStackItem ()
local _i=$1
local _fn=$FUNCNAME[$_i]; [[ $_fn =~ source

function inspFnStackTop ()
# top stack item is 1 less than length of FUNCNAME array stack
printf "%dn" $(( $#FUNCNAME[@] - 1 ))
#
return 0



Note that FUNCNAME, BASH_SOURCE and BASH_LINENO are 3 arrays maintained by bash as if they were one three-dimensional array.






share|improve this answer






























    0














    Just want to add that counting the array appears to be unreliable and one should probably not assume source was used since using a dot (.) is very common as well (and predates the source keyword).



    For example, for a sourced.sh script containing only echo $0:




    $ . sourced.sh
    bash
    $ source sourced.sh
    bash
    $ chmod +x sourced.sh
    $ ./sourced.sh
    ./sourced.sh
    $ cat ./sourced.sh
    echo $0


    The comparison solutions suggested work better.






    share|improve this answer






















      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',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      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%2f214079%2fdifferentiating-between-running-and-being-sourced-in-a-bash-shell-script%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      17














      Yes - the $0 variable gives the name of the script as it was run:



      $ cat example.sh
      #!/bin/bash
      script_name=$( basename $0#- ) #- needed if sourced no path
      this_script=$( basename $BASH_SOURCE )
      if [[ $script_name = $this_script ]] ; then
      echo "running me directly"
      else
      echo "sourced from $script_name"
      fi

      $ cat example2.sh
      #!/bin/bash
      . ./example.sh


      Which runs like:



      $ ./example.sh
      running me directly
      $ ./example2.sh
      example.sh sourced from example2.sh


      That doesn't cater for being source from an interactive shell, but you get this idea (I hope).



      Updated to include BASH_SOURCE - thanks h.j.k






      share|improve this answer

























      • Close enough. :) Small hindrance that I'll need to specify the script's name at least, but I'll take this answer if there are no other viable solutions...

        – h.j.k.
        Jul 6 '15 at 2:40















      17














      Yes - the $0 variable gives the name of the script as it was run:



      $ cat example.sh
      #!/bin/bash
      script_name=$( basename $0#- ) #- needed if sourced no path
      this_script=$( basename $BASH_SOURCE )
      if [[ $script_name = $this_script ]] ; then
      echo "running me directly"
      else
      echo "sourced from $script_name"
      fi

      $ cat example2.sh
      #!/bin/bash
      . ./example.sh


      Which runs like:



      $ ./example.sh
      running me directly
      $ ./example2.sh
      example.sh sourced from example2.sh


      That doesn't cater for being source from an interactive shell, but you get this idea (I hope).



      Updated to include BASH_SOURCE - thanks h.j.k






      share|improve this answer

























      • Close enough. :) Small hindrance that I'll need to specify the script's name at least, but I'll take this answer if there are no other viable solutions...

        – h.j.k.
        Jul 6 '15 at 2:40













      17












      17








      17







      Yes - the $0 variable gives the name of the script as it was run:



      $ cat example.sh
      #!/bin/bash
      script_name=$( basename $0#- ) #- needed if sourced no path
      this_script=$( basename $BASH_SOURCE )
      if [[ $script_name = $this_script ]] ; then
      echo "running me directly"
      else
      echo "sourced from $script_name"
      fi

      $ cat example2.sh
      #!/bin/bash
      . ./example.sh


      Which runs like:



      $ ./example.sh
      running me directly
      $ ./example2.sh
      example.sh sourced from example2.sh


      That doesn't cater for being source from an interactive shell, but you get this idea (I hope).



      Updated to include BASH_SOURCE - thanks h.j.k






      share|improve this answer















      Yes - the $0 variable gives the name of the script as it was run:



      $ cat example.sh
      #!/bin/bash
      script_name=$( basename $0#- ) #- needed if sourced no path
      this_script=$( basename $BASH_SOURCE )
      if [[ $script_name = $this_script ]] ; then
      echo "running me directly"
      else
      echo "sourced from $script_name"
      fi

      $ cat example2.sh
      #!/bin/bash
      . ./example.sh


      Which runs like:



      $ ./example.sh
      running me directly
      $ ./example2.sh
      example.sh sourced from example2.sh


      That doesn't cater for being source from an interactive shell, but you get this idea (I hope).



      Updated to include BASH_SOURCE - thanks h.j.k







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Dec 10 '16 at 18:12









      Stuart Rothrock

      32




      32










      answered Jul 6 '15 at 2:33









      DarkHeartDarkHeart

      3,52632340




      3,52632340












      • Close enough. :) Small hindrance that I'll need to specify the script's name at least, but I'll take this answer if there are no other viable solutions...

        – h.j.k.
        Jul 6 '15 at 2:40

















      • Close enough. :) Small hindrance that I'll need to specify the script's name at least, but I'll take this answer if there are no other viable solutions...

        – h.j.k.
        Jul 6 '15 at 2:40
















      Close enough. :) Small hindrance that I'll need to specify the script's name at least, but I'll take this answer if there are no other viable solutions...

      – h.j.k.
      Jul 6 '15 at 2:40





      Close enough. :) Small hindrance that I'll need to specify the script's name at least, but I'll take this answer if there are no other viable solutions...

      – h.j.k.
      Jul 6 '15 at 2:40













      6














      Combining @DarkHeart's answer with the environment variable BASH_SOURCE seems to do the trick:





      $ head example*.sh
      ==> example2.sh <==
      #!/bin/bash
      . ./example.sh

      ==> example.sh <==
      #!/bin/bash
      if [ "$(basename $0)" = "$(basename $BASH_SOURCE)" ]; then
      echo "running directly"
      else
      echo "sourced from $0"
      fi
      $ ./example2.sh
      sourced from ./example2.sh
      $ ./example.sh
      running directly


      edit Seems to be a simpler solution still if I were to just count the number of elements in BASH_SOURCE's array:



      if [ $#BASH_SOURCE[@] -eq 1 ]; then echo "running directly"; else echo "sourced from $0"; fi





      share|improve this answer




















      • 1





        Looks like we found the 'bash_source' variable at the same time. :)

        – DarkHeart
        Jul 6 '15 at 2:58











      • @DarkHeart I've added onto my answer the usage of counting the array size too... thanks for hinting me on this path! :D

        – h.j.k.
        Jul 6 '15 at 3:07















      6














      Combining @DarkHeart's answer with the environment variable BASH_SOURCE seems to do the trick:





      $ head example*.sh
      ==> example2.sh <==
      #!/bin/bash
      . ./example.sh

      ==> example.sh <==
      #!/bin/bash
      if [ "$(basename $0)" = "$(basename $BASH_SOURCE)" ]; then
      echo "running directly"
      else
      echo "sourced from $0"
      fi
      $ ./example2.sh
      sourced from ./example2.sh
      $ ./example.sh
      running directly


      edit Seems to be a simpler solution still if I were to just count the number of elements in BASH_SOURCE's array:



      if [ $#BASH_SOURCE[@] -eq 1 ]; then echo "running directly"; else echo "sourced from $0"; fi





      share|improve this answer




















      • 1





        Looks like we found the 'bash_source' variable at the same time. :)

        – DarkHeart
        Jul 6 '15 at 2:58











      • @DarkHeart I've added onto my answer the usage of counting the array size too... thanks for hinting me on this path! :D

        – h.j.k.
        Jul 6 '15 at 3:07













      6












      6








      6







      Combining @DarkHeart's answer with the environment variable BASH_SOURCE seems to do the trick:





      $ head example*.sh
      ==> example2.sh <==
      #!/bin/bash
      . ./example.sh

      ==> example.sh <==
      #!/bin/bash
      if [ "$(basename $0)" = "$(basename $BASH_SOURCE)" ]; then
      echo "running directly"
      else
      echo "sourced from $0"
      fi
      $ ./example2.sh
      sourced from ./example2.sh
      $ ./example.sh
      running directly


      edit Seems to be a simpler solution still if I were to just count the number of elements in BASH_SOURCE's array:



      if [ $#BASH_SOURCE[@] -eq 1 ]; then echo "running directly"; else echo "sourced from $0"; fi





      share|improve this answer















      Combining @DarkHeart's answer with the environment variable BASH_SOURCE seems to do the trick:





      $ head example*.sh
      ==> example2.sh <==
      #!/bin/bash
      . ./example.sh

      ==> example.sh <==
      #!/bin/bash
      if [ "$(basename $0)" = "$(basename $BASH_SOURCE)" ]; then
      echo "running directly"
      else
      echo "sourced from $0"
      fi
      $ ./example2.sh
      sourced from ./example2.sh
      $ ./example.sh
      running directly


      edit Seems to be a simpler solution still if I were to just count the number of elements in BASH_SOURCE's array:



      if [ $#BASH_SOURCE[@] -eq 1 ]; then echo "running directly"; else echo "sourced from $0"; fi






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Apr 13 '17 at 12:36









      Community

      1




      1










      answered Jul 6 '15 at 2:55









      h.j.k.h.j.k.

      825719




      825719







      • 1





        Looks like we found the 'bash_source' variable at the same time. :)

        – DarkHeart
        Jul 6 '15 at 2:58











      • @DarkHeart I've added onto my answer the usage of counting the array size too... thanks for hinting me on this path! :D

        – h.j.k.
        Jul 6 '15 at 3:07












      • 1





        Looks like we found the 'bash_source' variable at the same time. :)

        – DarkHeart
        Jul 6 '15 at 2:58











      • @DarkHeart I've added onto my answer the usage of counting the array size too... thanks for hinting me on this path! :D

        – h.j.k.
        Jul 6 '15 at 3:07







      1




      1





      Looks like we found the 'bash_source' variable at the same time. :)

      – DarkHeart
      Jul 6 '15 at 2:58





      Looks like we found the 'bash_source' variable at the same time. :)

      – DarkHeart
      Jul 6 '15 at 2:58













      @DarkHeart I've added onto my answer the usage of counting the array size too... thanks for hinting me on this path! :D

      – h.j.k.
      Jul 6 '15 at 3:07





      @DarkHeart I've added onto my answer the usage of counting the array size too... thanks for hinting me on this path! :D

      – h.j.k.
      Jul 6 '15 at 3:07











      1














      I just created the same kind of library script that works alot like BusyBox. In it, I use the following function to test if it is being sourced...



      function isSourced () 
      [[ "$FUNCNAME[1]" == "source" ]] && return 0
      return 1



      The Bash-maintained FUNCNAME array is essentially a function call stack. $FUNCNAME (or $FUNCNAME[0]) is the name of the currently executing function. $FUNCNAME[1] is the name of the function that called it, and so on.



      The topmost item is a special value for the script itself. It will contain...



      • the word "source" if the script is being sourced

      • the word "main" if the script is being executed AND the test is being done from within a function

      • ""(null) if the script is being executed AND the test is being done outside of any function, that is... at the level of the script itself.

      The function above actually only works when called at the script level (which is all I needed). It would fail if called from inside another function because the array item number would be wrong. To make it work anywhere requires finding the top of the stack and testing that value, which is more complicated.



      If you need that, you can get the array item number of the "top of the stack" with...



       local _top_of_stack=$(( $#FUNCNAME[@] - 1 ))


      $#FUNCNAME[@] is the number of items in the array. As a zero-based array, we subtract 1 to get the last item#.



      These three functions are used together to produce a function stack trace similar to Python's and they may give you a better idea how all this works...



      function inspFnStack () $i $T$(inspFnStackItem $i)n"
      T+=" "
      ((--i))
      done
      #
      printf "$_textn"
      #
      return 0


      function inspFnStackItem ()
      local _i=$1
      local _fn=$FUNCNAME[$_i]; [[ $_fn =~ source

      function inspFnStackTop ()
      # top stack item is 1 less than length of FUNCNAME array stack
      printf "%dn" $(( $#FUNCNAME[@] - 1 ))
      #
      return 0



      Note that FUNCNAME, BASH_SOURCE and BASH_LINENO are 3 arrays maintained by bash as if they were one three-dimensional array.






      share|improve this answer



























        1














        I just created the same kind of library script that works alot like BusyBox. In it, I use the following function to test if it is being sourced...



        function isSourced () 
        [[ "$FUNCNAME[1]" == "source" ]] && return 0
        return 1



        The Bash-maintained FUNCNAME array is essentially a function call stack. $FUNCNAME (or $FUNCNAME[0]) is the name of the currently executing function. $FUNCNAME[1] is the name of the function that called it, and so on.



        The topmost item is a special value for the script itself. It will contain...



        • the word "source" if the script is being sourced

        • the word "main" if the script is being executed AND the test is being done from within a function

        • ""(null) if the script is being executed AND the test is being done outside of any function, that is... at the level of the script itself.

        The function above actually only works when called at the script level (which is all I needed). It would fail if called from inside another function because the array item number would be wrong. To make it work anywhere requires finding the top of the stack and testing that value, which is more complicated.



        If you need that, you can get the array item number of the "top of the stack" with...



         local _top_of_stack=$(( $#FUNCNAME[@] - 1 ))


        $#FUNCNAME[@] is the number of items in the array. As a zero-based array, we subtract 1 to get the last item#.



        These three functions are used together to produce a function stack trace similar to Python's and they may give you a better idea how all this works...



        function inspFnStack () $i $T$(inspFnStackItem $i)n"
        T+=" "
        ((--i))
        done
        #
        printf "$_textn"
        #
        return 0


        function inspFnStackItem ()
        local _i=$1
        local _fn=$FUNCNAME[$_i]; [[ $_fn =~ source

        function inspFnStackTop ()
        # top stack item is 1 less than length of FUNCNAME array stack
        printf "%dn" $(( $#FUNCNAME[@] - 1 ))
        #
        return 0



        Note that FUNCNAME, BASH_SOURCE and BASH_LINENO are 3 arrays maintained by bash as if they were one three-dimensional array.






        share|improve this answer

























          1












          1








          1







          I just created the same kind of library script that works alot like BusyBox. In it, I use the following function to test if it is being sourced...



          function isSourced () 
          [[ "$FUNCNAME[1]" == "source" ]] && return 0
          return 1



          The Bash-maintained FUNCNAME array is essentially a function call stack. $FUNCNAME (or $FUNCNAME[0]) is the name of the currently executing function. $FUNCNAME[1] is the name of the function that called it, and so on.



          The topmost item is a special value for the script itself. It will contain...



          • the word "source" if the script is being sourced

          • the word "main" if the script is being executed AND the test is being done from within a function

          • ""(null) if the script is being executed AND the test is being done outside of any function, that is... at the level of the script itself.

          The function above actually only works when called at the script level (which is all I needed). It would fail if called from inside another function because the array item number would be wrong. To make it work anywhere requires finding the top of the stack and testing that value, which is more complicated.



          If you need that, you can get the array item number of the "top of the stack" with...



           local _top_of_stack=$(( $#FUNCNAME[@] - 1 ))


          $#FUNCNAME[@] is the number of items in the array. As a zero-based array, we subtract 1 to get the last item#.



          These three functions are used together to produce a function stack trace similar to Python's and they may give you a better idea how all this works...



          function inspFnStack () $i $T$(inspFnStackItem $i)n"
          T+=" "
          ((--i))
          done
          #
          printf "$_textn"
          #
          return 0


          function inspFnStackItem ()
          local _i=$1
          local _fn=$FUNCNAME[$_i]; [[ $_fn =~ source

          function inspFnStackTop ()
          # top stack item is 1 less than length of FUNCNAME array stack
          printf "%dn" $(( $#FUNCNAME[@] - 1 ))
          #
          return 0



          Note that FUNCNAME, BASH_SOURCE and BASH_LINENO are 3 arrays maintained by bash as if they were one three-dimensional array.






          share|improve this answer













          I just created the same kind of library script that works alot like BusyBox. In it, I use the following function to test if it is being sourced...



          function isSourced () 
          [[ "$FUNCNAME[1]" == "source" ]] && return 0
          return 1



          The Bash-maintained FUNCNAME array is essentially a function call stack. $FUNCNAME (or $FUNCNAME[0]) is the name of the currently executing function. $FUNCNAME[1] is the name of the function that called it, and so on.



          The topmost item is a special value for the script itself. It will contain...



          • the word "source" if the script is being sourced

          • the word "main" if the script is being executed AND the test is being done from within a function

          • ""(null) if the script is being executed AND the test is being done outside of any function, that is... at the level of the script itself.

          The function above actually only works when called at the script level (which is all I needed). It would fail if called from inside another function because the array item number would be wrong. To make it work anywhere requires finding the top of the stack and testing that value, which is more complicated.



          If you need that, you can get the array item number of the "top of the stack" with...



           local _top_of_stack=$(( $#FUNCNAME[@] - 1 ))


          $#FUNCNAME[@] is the number of items in the array. As a zero-based array, we subtract 1 to get the last item#.



          These three functions are used together to produce a function stack trace similar to Python's and they may give you a better idea how all this works...



          function inspFnStack () $i $T$(inspFnStackItem $i)n"
          T+=" "
          ((--i))
          done
          #
          printf "$_textn"
          #
          return 0


          function inspFnStackItem ()
          local _i=$1
          local _fn=$FUNCNAME[$_i]; [[ $_fn =~ source

          function inspFnStackTop ()
          # top stack item is 1 less than length of FUNCNAME array stack
          printf "%dn" $(( $#FUNCNAME[@] - 1 ))
          #
          return 0



          Note that FUNCNAME, BASH_SOURCE and BASH_LINENO are 3 arrays maintained by bash as if they were one three-dimensional array.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jul 11 '15 at 13:05









          DocSalvagerDocSalvager

          1,32021732




          1,32021732





















              0














              Just want to add that counting the array appears to be unreliable and one should probably not assume source was used since using a dot (.) is very common as well (and predates the source keyword).



              For example, for a sourced.sh script containing only echo $0:




              $ . sourced.sh
              bash
              $ source sourced.sh
              bash
              $ chmod +x sourced.sh
              $ ./sourced.sh
              ./sourced.sh
              $ cat ./sourced.sh
              echo $0


              The comparison solutions suggested work better.






              share|improve this answer



























                0














                Just want to add that counting the array appears to be unreliable and one should probably not assume source was used since using a dot (.) is very common as well (and predates the source keyword).



                For example, for a sourced.sh script containing only echo $0:




                $ . sourced.sh
                bash
                $ source sourced.sh
                bash
                $ chmod +x sourced.sh
                $ ./sourced.sh
                ./sourced.sh
                $ cat ./sourced.sh
                echo $0


                The comparison solutions suggested work better.






                share|improve this answer

























                  0












                  0








                  0







                  Just want to add that counting the array appears to be unreliable and one should probably not assume source was used since using a dot (.) is very common as well (and predates the source keyword).



                  For example, for a sourced.sh script containing only echo $0:




                  $ . sourced.sh
                  bash
                  $ source sourced.sh
                  bash
                  $ chmod +x sourced.sh
                  $ ./sourced.sh
                  ./sourced.sh
                  $ cat ./sourced.sh
                  echo $0


                  The comparison solutions suggested work better.






                  share|improve this answer













                  Just want to add that counting the array appears to be unreliable and one should probably not assume source was used since using a dot (.) is very common as well (and predates the source keyword).



                  For example, for a sourced.sh script containing only echo $0:




                  $ . sourced.sh
                  bash
                  $ source sourced.sh
                  bash
                  $ chmod +x sourced.sh
                  $ ./sourced.sh
                  ./sourced.sh
                  $ cat ./sourced.sh
                  echo $0


                  The comparison solutions suggested work better.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Feb 17 at 15:02









                  ka1lka1l

                  11




                  11



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Unix & Linux Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f214079%2fdifferentiating-between-running-and-being-sourced-in-a-bash-shell-script%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown






                      Popular posts from this blog

                      Peggy Mitchell

                      Palaiologos

                      The Forum (Inglewood, California)