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?
~/.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.
function myFunction { ... }
in ~/.bash_profile
and you're good to go?
Commented
Feb 4, 2013 at 16:34
export
solution seems to work properly. Thanks.
Commented
Feb 4, 2013 at 16:53
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.
Commented
Feb 4, 2013 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"
}
Do you need a function? If not, consider pulling out the logic into a separate, stand-alone Bash script in your $PATH
. For example, I had this in my ~/.bashrc
:
# echo public IP address
alias wanip='dig +short myip.opendns.com @resolver1.opendns.com'
~/bin
is in my $PATH
, so I created ~/bin/wanip
with the following contents:
#!/bin/bash
# echo public IP address
dig +short myip.opendns.com @resolver1.opendns.com
And ran chmod 0755 ~/bin/wanip
to make it executable. Now I can execute wanip
from other scripts.
I like having wanip
in a stand-alone Bash script. It reminds me that I want this logic generally available (besides just in my current interactive Bash session). The script nicely encapsulates the logic and documentation for same.
/bin/sh
in the shebang line?