0

I am trying to create a custom Mac Terminal command, start, In Terminal, my intent is to write $ start func1 subfunc myText, where func is a function in the start.sh file and subfunc is a function only in func that can only be called from in func. So $ start subfunc myText wouldn't be possible. I see that its possible to pass a function from another (Here), but only when both are in the outer scope of the start.sh file.

Basically:

start.sh:

function func(){
  function subfunc(){
    echo $1
  }
}

and then in Terminal: $ start func subfunc Hey prints Hey

4
  • 1
    I don't think bash has nested function scopes like this. Commented Nov 13, 2018 at 21:51
  • 2
    What is it supposed to achieve? Even if it works (it doesn't), Anyone who can't do start subfunc myText can still do start func subfunc Hey do still call subfunc anyway. What problem are you trying to solve with this? Commented Nov 13, 2018 at 21:58
  • This feels like similar functionality to like an aws console command? I don't think bash is the right place to write this though. If you did, I think you would need to catch those arguments to variables and then perform logic based on what is in those variables if [$command = "func"] if [ $subcommand = "subfunc"] sort of thing... IT may help if you explained what you are trying to achieve though since it's not clear from your very not-working code. Commented Nov 13, 2018 at 22:06
  • Sorry, I haven't used bash before and couldn't find great documentation for this. I was trying to create a custom hierarchy of commands to do something like nodecontroller nodestart node1 start, or something with a hierarchy of commands like this. Commented Nov 14, 2018 at 1:31

2 Answers 2

2

You need to call the functions, not only declare them:

func() {
   subfunc() {
      echo "$1"
   }
   "$@"
}
"$@"

However functions have no scopes, so once you declare the function inside another function it overwrites the previous declaration. So I would advise so to make each function and sub-function name unique.

f() {
  f() {
    echo in
  }
  echo out
}

f // will print 'out'
f // will print 'in'

Note that using function name() {} is accepted, but not really valid. Use name() { }, as function name {} is not specified by posix.

Sign up to request clarification or add additional context in comments.

Comments

2

You don't need nested functions for this. I think this is an argument parsing problem:

#!/bin/bash

start() {
    case $1 in 
        func) shift; do_func "$@" ;;
        *) echo "unknown subcommand"; exit 1 ;;
    esac
}

do_func() {
    case $1 in
        subfunc) shift; do_subfunc "$@" ;;
        *) echo "unknown sub-subcommand"; exit 1 ;;
    esac
}

do_subfunc() {
    echo "$1"
}

start "$@"

Then

$ ./start func foo
unknown sub-subcommand
$ ./start func subfunc 'hello world'
hello world

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.