Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I can define a function like:

myfunction () { ls -R "$1" ; }

And then

myfunction .

just works.

But if I do

echo "myfunction ." | sh
echo "myfunction ." | bash

the messages are:

sh: myfunction: not found  
bash: line 1: myfunction: command not found

Why? And how can I call a function that comes from a string if not by piping it to sh or bash?

I know there is this command source, but I am confused of when I should use source and when sh or bash. Also, I cannot pipe through source. To add to confusion, there is this command . that seems to have nothing to do with the "." that means "current directory".

share|improve this question
add comment

3 Answers

up vote 5 down vote accepted

A function definition only has an effect in the current instance of bash. When you write

echo "myfunction ." | bash

you run another instance of bash. You would need to define the function in that other instance.

If you have a string that contains a function name and arguments (quoted, if necessary), or more generally any string that contains some shell source code that you want to execute, use the eval builtin.

my_snippet='myfunction .'
eval "$my_snippet"

If you define functions in your .bashrc, they are only available in interactive shells, not in scripts.

The . command is (almost) equivalent to source, and has nothing to do with . meaning the current directory.

share|improve this answer
add comment

Instead of using eval, you can export your function so it is inherited by subshells:

myfunction () { ls -R "$1" ; }
export -f myfunction

And then

echo "myfunction ." | bash

just works.

echo "myfunction ." | sh probably won't still, unless your /bin/sh is a symlink to bash.

share|improve this answer
add comment

bash and sh expect their argument to be an executable file, not a string.

You can execute the contents of a string with

eval "myfunction ."

When you run a program through the shell, it will normally invoke a new instance of bash (or sh, csh, zsh, etc. as appropriate), inherit all the original shell's settings, and run itself in the new shell. This allows you to temporarily set variables or change settings without interfering with your environment.

sourceing a command will make it run it your current shell, so any changes it makes to the environment will persist when the command exits. . is a synonym for source.

In most circumstances, a script will specify what shell it is meant to run in (with #!/bin/bash in its first line, for example), and it isn't necessary for you to call bash explicitly.

share|improve this answer
    
A command like echo "myfunction ." | bash is not passing myfunction . to bash as a command-line argument. It's running bash and piping it the text myfunction . in lieu of standard input. That's totally different. –  Eliah Kagan Jun 4 '12 at 0:30
    
You're completely right. Thanks for the reminder. –  pconley Jun 4 '12 at 4:41
add comment

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.