source some_file


doit ()
  echo doit $1
export TEST=true

If I source some_file the function "doit" and the variable TEST are available on the command line. But running this script:


echo $TEST
doit test2

Will return the value of TEST, but will generate an error about the unknown function "doit".

Can I "export" the function, too, or do I have to source some_file in script.sh to use the function there?

  • 2
    summarizing answers below (enzotib is correct, assuming you can use bash, as the question indicates): change #!/bin/sh to #!/bin/bash and after doit() {...} just export -f doit
    – michael
    Commented Jun 11, 2013 at 21:08
  • Just for the record: This solution will usually work when you use #!/bin/sh too, but it is good practice to use #!/bin/bash so that you avoid problems when the default shell is not bash.
    – Nagel
    Commented Aug 5, 2014 at 12:16
  • @Nagel sh: 1: export: Illegal option -f
    – sol
    Commented Feb 27 at 7:50

8 Answers 8


In Bash you can export function definitions to other shell scripts that your script calls with

export -f function_name

For example you can try this simple example:



myfun() {
    echo "Hello!"

export -f myfun




Then if you call ./script1 you will see the output Hello!.

  • 3
    To clarify, for those who are wondering: it does not work with zsh (according to my testing). It also only works from bash -> bash, not bash -> zsh.
    – Neil Traft
    Commented Oct 22, 2021 at 13:39

"Exporting" a function using export -f creates an environment variable with the function body. Consider this example:

$ fn(){ echo \'\"\ \ \$; }
$ export -f fn
$ sh -c printenv\ fn
() {  echo \'\"\ \ \$

This means that only the shell (just Bash?) will be able to accept the function. You could also set the function yourself as the Bash only considers envvars starting with () { as function:

$ fn2='() { echo Hi;}' sh -c fn2
$ fn3='() {' sh -c :
sh: fn3: line 1: syntax error: unexpected end of file
sh: error importing function definition for `fn3'

If you need to "export" this variable over SSH, then you really need the function as a string. This can be done with the print option (-p) for functions (-f) of the declare built-in:

$ declare -pf fn
fn () 
    echo \'\"\ \ \$

This is very useful if you have more complex code that needs to be executed over SSH. Consider the following fictitious script:

remote_main() {
   local dest="$HOME/destination"

   tar xzv -C "$dest"
   chgrp -R www-data "$dest"
   # Ensure that newly written files have the 'www-data' group too
   find "$dest" -type d -exec chmod g+s {} \;
tar cz files/ | ssh user@host "$(declare -pf remote_main); remote_main"
  • 3
    fn2='() { echo Hi;}' sh -c fn2 did not work for me. On arch linux with sh being bash v5.0.7 I got sh: fn2: command not found. On Ubuntu with with sh being dash v0.2.3 I got sh: 1: fn2: not found. Which sh shell did you use?
    – Socowi
    Commented Jul 2, 2019 at 16:03
  • 2
    I think your answer is wrong. f(){ echo a;}; export -f f; echo "$f"; sh -c 'printenv f; echo "$f"' prints nothing for me, so clearly f isn't exported as a plain string. I tested with both combinations mentioned above.
    – Socowi
    Commented Jul 2, 2019 at 16:16
  • 3
    And even if the function was exported as a string, why should sh execute that string as a function? In your example fn2='() { echo Hi;}' sh -c fn2 the command fn2 given to sh is literally the string "fn2". sh should search for such a command in its PATH but should not look if there is a variable $fn2, expand that variable, and execute its value as a function – sounds like a major security issue to me. edit: I think that's it! Was your shown behavior the security bug known as ShellShock/Bashdoor?
    – Socowi
    Commented Jul 2, 2019 at 16:26
  • 5
    With Bash 5.0.7 (Arch Linux), it appears that a prefix is prepended. This was likely done in response to ShellShock. Example: fn(){ echo foo; }; export -f fn; env | grep foo outputs BASH_FUNC_fn%%=() { echo foo
    – Lekensteyn
    Commented Jul 2, 2019 at 22:04

Building on @Lekensteyn's answer...

If you use declare -pf it will output all the previously defined functions in the current shell to STDOUT.

At that point you can redirect STDOUT to wherever you want and in effect stuff the previously defined functions wherever you want.

The following answer will stuff them into a variable. Then we echo that variable plus the invocation of the function that we want to run into the new shell that is spawned as a new user. We do this by using sudo with the -u (aka. user) switch and simply running Bash (which will receive the piped STDOUT as the input to run).

As we know that we are going from a Bash shell to a Bash shell we know that Bash will interpret the previous shells defined functions correctly. The syntax should be fine as long as we are moving between one Bash shell of the same version to a new Bash shell of the same version.

YMMV if you are moving between different shells or between systems that may have different versions of Bash.

foo() {
  echo "hello from `whoami`"

FUNCTIONS=`declare -pf`; echo "$FUNCTIONS ; foo" | sudo -u otheruser bash
# $./test.sh
# hello from otheruser

You cannot export functions, not in the way that you are describing. The shell will only load the ~/.bashrc file on the start of an interactive shell (search for "Invocation" in the bash manpage).

What you can do is create "library" which is loaded when you start the program:

source "$HOME/lib/somefile"

And place your non-interactive functions and settings there.

  • So I have to either start the subshell with the "login" parameter (to parse ~/.profile) or source that file.
    – Nils
    Commented Oct 17, 2011 at 19:11
  • Looking a little more closely, on non-interactive shells, you could set BASH_ENV environment variable to some_file you already have, and it would be called. It would be easy enough to find that out: echo echo foobar > /tmp/foobar; BASH_ENV=/tmp/foobar $SHELL -c :
    – Arcege
    Commented Oct 17, 2011 at 19:20
  • For some reason this isn't working for me. I've written plenty of shell scripts, including library scripts. For some reason, even though my .profile is successfully sourcing my .bashrc (I tested by echoing a variable that would have been sourced). I just can't figure out why it can't find my function, but it can find a var to echo.
    – Ungeheuer
    Commented Dec 25, 2020 at 2:05
  • I realize it's been a long time, but this is a VERY useful way to load all your functions into the shell, and then execute them as needed for your main script. In a long script, sometimes you run into issues where one function must be loaded before another (you get "[script name:] line [number:] [function name:] command not found", but in the "library" it doesn't matter what order they are in.
    – Wastrel
    Commented Jan 18, 2023 at 20:10
  • 1
    You seem to be saying that export -f doesn't exist. Commented Jun 22, 2023 at 19:24

eval "$(declare -F | sed -e 's/-f /-fx /')" will export all functions.

I do this a lot before starting an interactive shell in a script to enable me to debug and work in the script context while using its functions and variables.


eval "$(declare -F | sed -e 's/-f /-fx /')"
bash -i

Functions are not exported to subprocesses. This is why there are files named .kshrc or .bashrc: To define functions that shoiuld be available in subshells also.

If running a script, the .*shrc scripts are normally not sourced. You would have to code that explicitly, like in . ~/.kshrc.

  • So the ~root/.bashrc could be an option in my case, since the scripts are run as root. Thanks for that hint.
    – Nils
    Commented Oct 17, 2011 at 19:06
  • if using the .*shrc files, be sure they dont force interactive behaviour (like the stupid alias rm=rm -i)
    – ktf
    Commented Oct 18, 2011 at 8:50

Well, I'm new to Linux, but you can try this. In some file, let's call it, 'tmp/general' you build your function:

   echo "func from general"

In your shell script add:

. /tmp/general

and run:


You'll get on the screen: func from general.

declare -x -f NAME

More info

-f        restrict action or display to function names and definitions
-x        to make NAMEs export

You must log in to answer this question.

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