0

I have a function defined in my .zshenv like this:

function my_func() {
echo $1
}

I then execute a bash script from the zsh which its content is:

type my_func

I got an error: /tmp/test.bash: line 3: type: my_func: not found

While if I type type my_func from the zsh I got: my_func is a shell function from

Is there a way to use zsh defined function in a bash script? It seems to work for the exported variables

1
  • If you have written the function in a way, that it works the same in bash and in zsh (which can be a challenge), put the function definition in some file and source it from there in your zsh-script, respectively in your bash-script. Note that even your innocent example function would exhibt slightly different behaviour in bash and in zsh, if called for instance by my_func 'a b c' (observe the difference in spacing in the output!). Commented May 5, 2021 at 7:45

1 Answer 1

3

How bash does it

Bash itself can export its functions to other bash shells. It does so by exporting a string environmental variable of the form:

BASH_FUNC_functionNameHere%%=() { functionBodyHere; }

So in theory you could use the following zsh-command to export your function for bash:

export "BASH_FUNC_my_func%%=() { $(echo; typeset -f my_func | tail -n+2) }"

However, this does not work because zsh doesn't allow %% in identifiers.

Workaround

Depending on how you start bash, you might be able to inject the function definition into the bash process.

  • When running a bash script like bash myScript or ./myScript you can use bash -c "$(typeset -f my_func); export -f my_func; myScript" instead.

  • When starting an interactive bash shell using bash, you can use bash -c "$(typeset -f my_func); export -f my_func; exec bash" instead.

The right way

Either way, your function has to be a polyglot. That is, the source code of the function has to be understood by both zsh and bash. Above approach is not really viable if you want to export many functions or want to call many bash scripts.

It would be easier to define each of your functions inside its own script file and add the locations of those scripts to $PATH. That way you can call your "functions" from every shell and they will always work independently from your current shell.

Replacing the functions by script files only works if your functions don't want to modify the parent shell. cd or setting variables has no effect on the caller. If you want to do stuff like this, you can still use a script file, but then have to source it using . myFunctionFile. For sourcing, the source code has to be a polyglot again.

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

2 Comments

Is this way of exporting functions a bash 5 feature? My bash 4.4.12 does not allow it. BTW, you can get around the zsh name restriction on the % in a variable name by retrieving the variable in zsh using bash_func=$(printenv BASH_FUNC_my_func%%).
I'm not sure which command does not work for you. I wrote that export "BASH_FUNC_... does not work in zsh, but that doesn't mean that it works in bash (as expected, it doesn't; neither in bash 4, nor bash 5). The other commands worked in bash 4.4.12 and 5.1.4. For the script version (first bullet point) I just added a missing export. ¶ BTW Your suggestion assumes that OP wanted to export a function from bash to zsh when they actually want to export it the other way around.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.