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.

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?

share|improve this question

marked as duplicate by Stéphane Chazelas, jasonwryan, manatwork, Renan, Shadur Jan 23 '13 at 12:04

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

    
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 4: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 6:43
    
Of course -exec has problem with any bash built-in command. –  Mohsen Pahlevanzadeh Jan 23 '13 at 6:46

3 Answers 3

up vote 1 down vote accepted

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.

share|improve this answer

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
share|improve this answer
    
Thank you Hai, But my question is conceptually ,,,,, not coding.... –  Mohsen Pahlevanzadeh Jan 23 '13 at 3:41
    
I understand, but I cannot answer that. I'm in the same boat. –  Hai Vu Jan 23 '13 at 3:48
    
May be developer of find can answer us.... by the way , your solution is very good solution. thank you. –  Mohsen Pahlevanzadeh Jan 23 '13 at 3:57
1  
This will break on any file containing a space. –  jordanm Jan 23 '13 at 4:10
    
change the field separator to new line (IFS=$'\n') should make the for loop work if file name contains white spaces –  LiuYan 刘研 Jan 23 '13 at 4:38

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.

share|improve this answer

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