Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have defined a bash function in my ~/.bashrc file. This allows me to use it in shell terminals. However, it does not seem to exist when I call it from within a script.

How can I define a bash function to be used by scripts as well?

share|improve this question
    
But my .bash_profile basically reads the .basrc file, so I would expect the result to be the same regardless I use login or non-login shell. –  Onturenio Feb 4 '13 at 16:17
    
Are you using /bin/sh in the shebang line? –  Kevin Feb 4 '13 at 16:21
1  

2 Answers 2

up vote 3 down vote accepted

~/.bash_profile and ~/.bashrc are not read by scripts, and functions are not exported by default. To do so, you can use export -f like so:

$ cat > script << 'EOF'
#!/bin/bash
foo
EOF
$ chmod a+x script
$ ./script
./script: line 2: foo: command not found
$ foo() { echo "works" ; } 
$ export -f foo
$ ./script
works

export -f foo could also be called in ~/.bash_profile to make this function available to scripts after login. Be warned that export -f is not portable.

A better solution would be to source the file containing the function using . file. This is much more portable, and doesn't rely on your environment being set up in a particular way.

share|improve this answer
    
why not just declare a function like function myFunction { ... } in ~/.bash_profile and you're good to go? –  amphibient Feb 4 '13 at 16:34
    
If I understood properly your answer (regarding sourcing a file with the function), this would mean that I have to source the file explicitly in every script, which is pretty much annoying. This is not much less complicated than just copy-pasting the function itself in every script. I would save some lines, sure, but that's all. However, the export solution seems to work properly. Thanks. –  Onturenio Feb 4 '13 at 16:53
    
@foampile, this is precisely what I did and does not work when calling the function from a script. –  Onturenio Feb 4 '13 at 16:56
1  
@Onturenio : the second method @chris-down proposed is indeed better: 1) When someone read the script, they are aware that it needs some foo function from some file 2) You can better control the content of that file than make sure that the invoking shell didn't change foo before invoking your script. You could add safety checks on file to make sure it's untampered, for example. (not easy, but possible). (well, you could also do those checks on the defined foo function... but you get my drift ^^ I think the method 2 is cleaner.) 3) file will only contain what's needed, not more. –  Olivier Dulac Feb 4 '13 at 17:25

.bashrc is only read by interactive shells. (Actually, that's an oversimplification: bash is quirky in this respect. Bash doesn't read .bashrc if it's a login shell, interactive or not. And there's an exception even to the exception: if bash's parent process is rshd or sshd, then bash does read .bashrc, whether it's interactive or not.)

Put your function definitions in a file in a known place, and use the . (also spelled source) builtin to include that file in a script.

$ cat ~/lib/bash/my_functions.bash
foo () {
…
$ cat ~/bin/myscript
#!/bin/bash
. ~/lib/bash/my_functions.bash
foo bar

If you want, you can follow ksh's autoload feature. Put each function definition in a file with the same name as the function. List the directories containing the function definitions in the FPATH variable (a colon-separated list of directories). Here's a crude approximation of ksh's autoload which actually loads the function immediately instead of on-demand:

autoload () {
  set -- "$(set +f; IFS=:;
            for d in $FPATH; do
              if [ -r "$d/$1" ]; then echo -E "$d/$1"; break; fi;
            done)"
  [[ -n $1 ]] && . "$1"
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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