I can define a function like:
myfunction () { ls -R "$1" ; }
And then
myfunction .
just works.
But if I do
echo "myfunction ." | sh
echo "myfunction ." | bashthe messages are:
sh: myfunction: not found
bash: line 1: myfunction: command not foundWhy? 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".
3 Answers
Instead of using eval, you can export your function so it is inherited by subshells:
myfunction () { ls -R "$1" ; }
export -f myfunctionAnd then
echo "myfunction ." | bashjust works.
echo "myfunction ." | sh probably won't still, unless your /bin/sh is a symlink to bash.
A function definition only has an effect in the current instance of bash. When you write
echo "myfunction ." | bashyou 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.
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.