5

Possible Duplicate:
Executing user defined function in a find -exec call

Suppose I have the following bash code:

!#/bin/bash
function  print_echo (){
    echo "This is print_echo Function" $1;
}
find ./ -iname "*" -exec print_echo {} \;

For each -exec command i get the following error:

find: `print_echo': No such file or directory

NOTE: Before it , i tested it for a critical program , and solved my program with another algorithm but it's a question: Why find command doesn't accept built-in bash command and function name as argument of -exec?

PersianGulf
  • 10,850
  • A side point - find with no args has the same behavior as find ./ -iname "*". Current directory and "match everything" is implied. – jordanm Jan 23 '13 at 04:44
  • 1
    @jordanm, find without file arguments is not standard/portable, but it's true that the -iname "*" is superfluous. Another side point: use the Bourne function syntax (f() { ...; }) or the ksh syntax (function f { ...; }), not that bastard one (function f() { ...; }) which is only recognised by accident by bash (because it ignores function) and is the syntax of no shell. – Stéphane Chazelas Jan 23 '13 at 06:43
  • Of course -exec has problem with any bash built-in command. – PersianGulf Jan 23 '13 at 06:46

3 Answers3

2

I don't know why find does not like function. The work around is as follow:

#!/bin/bash
function  print_echo (){
    echo "This is print_echo Function" $1;
}

for f in $(find . -iname "*")
do
    print_echo $f
done

Update

The above script does not work with files that have embedded spaces. The following update does:

#!/bin/bash
function  print_echo (){
    echo "This is print_echo Function" $1;
}

find . -iname "*.sh" | \
while read f
do
    print_echo "$f"
done
Hai Vu
  • 1,201
1

The find does not accept your function as a command because its -exec predicate literally calls C library exec function to start the program. Your function is available only to the bash interpreter itself. Even if you define your function inside your .bashrc file it will be 'visible' only to the bash.

So, if you really need two execute with find's -exec some custom sequence of commands put it into a separate script file or use other workarounds.

Serge
  • 8,541
1

You can launch a bash interpreter in the -exec argument of find. This is not efficient if your function only accepts a single filename at a time, as it will have to redeclare the function each time. You can design it so that it accepts a list of files and use the + terminator to find so that the shell is only spanwed once. Here is an example.

find -exec bash -c '
    print_echo() { 
        printf "This is print_echo Function: %s\n" "$@" 
    }
    print_echo "$@"
    ' find-bash {} +

At this point, there is not reason to declare the function. Just execute what the function would have done inside of the bash -c.

jordanm
  • 42,678