I have a sh (shebang #!/bin/sh) script (sh.sh) which invokes a bash (shebang #!/bin/bash) sub-script:

. "some-path/bash.sh"

In the bash script I have a declaration of an associative array: declare -A properties, thus getting the error declare: not found.

It's obvious why declare isn't found as the parent script is a sh script and not bash.

Is there a way to force bash syntax?

Another way is to open a new shell, but it's problematic because the subscript's purpose is to define variables to be used in the parent script. Sub-shells shouldn't be messing with parent's variable.

Parent (sh.sh):

. "some-path/bash.sh"

Child (bash.sh):

declare -A properties

Usage I was trying:

  • Please edit your question and give us enough of the script to reproduce the issue. – terdon Jul 18 '16 at 16:05
  • 1
    Note: do not use file extensions for executable files. It is bad form, and makes if difficult if you were to rewrite in python, perl, C (as the extension would change, and all programs that call your program would have to change). – ctrl-alt-delor Jul 18 '16 at 16:08
  • @terdon - Added scripts to reproduce. – AlikElzin-kilaka Jul 18 '16 at 16:11

Do not source the script (source script or . script).

Instead just run it normally script.

| improve this answer | |
  • Won't your proposal open a new shell? I'd like to avoid this because the sub-script defined variable that should be used by the parent script. – AlikElzin-kilaka Jul 18 '16 at 16:07
  • 4
    If you want to avoid creating a new shell, then it is mathematically impossible for the new shell to be bash (as there is no new shell). Re-write everything, so that it is all in the same language. – ctrl-alt-delor Jul 18 '16 at 16:11
  • @AlikElzin-kilaka If you use export on a variable at any point, it becomes visible to subprocesses. var=blah; : do_stuff_with var; export var; bash -c 'echo "$var"'. However, these subprocesses cannot modify the variable. One way around that would be to use a pipe to transfer state from that shell to yours once you're done. – Score_Under Jul 29 '16 at 14:12
  • @Score_Under a sub-process can modify an environment-variable, but its new value is only visible to it self, and is passed to its sub-processes (when they start). Therefore, as you say, environment-valiables are no good for back communication. They are also not real-time (you can only send a message as the process is started. – ctrl-alt-delor Aug 11 '16 at 16:19

Instead of running the parent script as is: ./sh.sh, I ran it using bash: bash sh.sh. Worked.

I have a hidden assumption that sh is a subset of bash. Not sure if it's correct, but worked.

| improve this answer | |
  • 1
    Whether sh is a subset of bash or not will depend on what sh actually is on your system. You haven't told us what OS you're using so we can't know that. That said, your question shows you're sourcing the script (. script.sh) but your answer shows you executing it. Which is it? – terdon Jul 18 '16 at 16:06
  • I'm executing the parent which sources the child. – AlikElzin-kilaka Jul 18 '16 at 16:08
  • 2
    Yes, it works, but you're making your code needlessly brittle. The child program is a bash script because it starts with #!/bin/bash. The kernel knows how to execute that. So just call the child script directly. – Gilles 'SO- stop being evil' Jul 18 '16 at 23:46
  • 1
    I don't have control over the parent script. I'm just executing it and it executes a my "plugin" script. See example "catalina.sh" file. Mine is "setenv.sh": github.com/magro/msm-sample-webapp/blob/master/runtime/… – AlikElzin-kilaka Jul 19 '16 at 4:13
  • 1
    maybe call awk or perl from your sourced script? you're not going to able to return the array anyway, only use it within that script. – cas Jul 19 '16 at 7:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.