0

In order to take advantage of some IDEs' hugely helpful tree/outline features, in scripts that have gotten a little unwieldy; things need to be nested for them to become a collapsible tree, e.g;

Collapsed function in script's outline view

As I understand (I'm a beginner still), functions are executed in the same shell, i.e. not in a sub shell; so considering that, it occurred to me I could just group large groups of functions, precede them with set -a and wrap 'em up in another function, e.g;

functiongroup() {        # ← moved from this level ─╮
  set -a                 #                         ╭╯
  func1() { …;}          #   ← grouped functions ──┤
  func2() { …;}          #   ← grouped functions ──╯
  …                      #
}                        #
…                        #
functiongroup            # ← invoke functions function

…or by declaring them properly with declare.

Could this cause problems?

Asuming it wouldn't, would they — or rather the new parent function — need to be called so they are known to Bash up a given position within the script? Let me rephrase that: does Bash process (is aware of) nested functions before their parent is executed?

Say, if the code were:

  1 │ #!/usr/bin/env bash
  2 │ # FUNCTIONS & VARS
  3 │ functiongroup() {                # ← moved from this level ─╮
  4 │   set -a                         #                         ╭╯
  5 │   func1() { …;}                  #   ← grouped functions ──┤
  6 │   func2() { …;}                  #   ← grouped functions ──╯
  7 │   …                              #
  8 │ }                                #
  9 │ # PROGRAM                        #
 10 │                                  # ← moved to line 12
 11 │ echo -n "something $(func2)"     # ← func2 call
 12 │ functiongroup                    # ← accidentally moved a line too late
 13 │ if func1; then                   # ← func1 call                  
 14 │   do                             #         
 15 │     …                            #         
 16 │   done                           #           
 17 │ else                             #       
 18 │   echo "MELTDOWN!"               #           
 19 │   exit 1                         #           
 20 │ fi                               #           
 21 │ exit 0                           #           

Above, would func1 and func2 run, or just func1? (if at all)

My references are GNU's Bash manual which can be a little too dense at times so I compare with this cheat sheet I found and A LOT of StackExchange for ideas but I don't use* code if I can't fully understand it, so I'm not learning as fast as I would like. Certainly not linearly. :(

I liked this because it's straightforward and you can always degroup in-place the functions for the final script, but if there's a proper/better way of organization, please do say.

Thanks.


*: Although I still save code snippets in my notes for reference that I review later when I reach the knowledge level it requires…provided I remember about it at all. Bash, PHP, Python, JavaScript, PowerShell, even HTML… there's kind of a backlog of unreviewed code hoarding in there.

2 Answers 2

1

does Bash process (is aware of) nested functions before their parent is executed?

No.

Let's try it:

$ funcgroup() {
    f1() { echo this is f1; }
    f2() { echo this is f2; }
}

$ f2
f2: command not found

$ funcgroup

$ f2
this is f2

If your scripts are getting unwieldy, break the functions out into libraries:

$ bash

$ cat funcs.bash
f1() { echo this is f1; }
f2() { echo this is f2; }

$ f2
f2: command not found

$ . funcs.bash

$ f2
this is f2

The . (aka source) command looks in the current directory and the PATH to find the file.

1
  • That's enlightening to say the least, not ., I knew about that, but the concept of libraries. The bad is that I want it to be self-contained w/o it fetching things from the Internet or elsewhere. It was much simpler but I added error check/predict/correct + keeping the output minimal to 1page but still useful, have 1st run awareness for some reason, be both inter. & not. I didn't know w I was getting into. Back to .ing though, putting it as libraries blew my mind open; in the manual "library" is almost always next to C/Readline, oh! and ncurses which I'm itching to learn too! Thanks!
    – Vita
    Oct 30, 2022 at 9:49
0

As pointed out by the first answer, it is usually a good idea to sort procedures into separate modules, especially the bloatware, which takes up too much space.

However, the issue with that is, that you need to be careful how you call your script. It makes a difference from where you call the initial script, which sources any library, because then paths change and the initial script may end up not finding any library.

I usually circumvent this problem with the following function.

function whereAmI { printf "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"; }

This tells you where the script running this procedure is.

So, it will always find the libraries, if the libraries are in some place relative to the initial script, e.g. lib/, if you prepend the result from whereAmI to that relative path.

Either way, it's highly important to organise Bash code really well, due to how limited the language is. Otherwise, you will look at it a year later from now and nothing will make sense.

2
  • I'm aggregating smaller scripts w a nicer UI, error checking, etc. I hope when I deduplicate their functions it'll get manageable again, meantime it's kind of a PITA. Bash is the 1st lang I've explored bc I could solve real problems easily, eg; 1 of my scripts gets,converts,distributes,installs&keepsinsync certs across platform—wasn't hard. But, as little as I know about it I'm starting to see those lims. u mntion. I've thought abt Python but I don't if it'd b apples≠oranges; if I'll be able to use it for actual tasks like I do w Bash or if it's more like a building block for a bigger thing.
    – Vita
    Oct 30, 2022 at 10:19
  • In my personal view, Python is like Bash, but it feels a bit more like a "real" language, rather than a pure utility scripting language, like Bash. I strongly suggest, that Python is generally way overhyped, overused, overrecommended and by far does not even remotely deserve all the praise it gets. It's a tiny bit better than Bash, that's it. So, for you, I think it wouldn't be a big deal to switch from Bash to Python. It wouldn't improve much, except you are dealing a LOT with data structures based on JSON, XML or something.
    – Akito
    Oct 30, 2022 at 16:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .