LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Several "find -exec" and "find | xargs" questions (https://www.linuxquestions.org/questions/programming-9/several-find-exec-and-find-%7C-xargs-questions-388476/)

thanhvn 12-01-2005 08:52 PM

Several "find -exec" and "find | xargs" questions
 
1) How do I get "find -exec" in a script to call a function also defined in that script?

For example, I wanted to do something like this:
Code:

#!/bin/sh
Function1() {
    # This function takes one argument
    # blah blah blah
}
find srcDir -name *.log -exec Function1 {} \;

The thing is -exec does not recognize Function1.

2) How to use command replacements with the backtick in "find -exec"?

As a trivial example, I wanted to do something like this:
Code:

#!/bin/sh
find srcDir -name *.log -exec echo `dirname {}` \;

However, this does not come out right.

3) How can I use the output from "find" at several places in "xargs"?

For example, I wanted to do something like this:
Code:

#!/bin/sh
find srcDir -name *.log | xargs python pyScript {} `dirname {}`\/python.log

However, it seems that I cannot use {} in xargs and xargs will only append whatever is piped from find to the end of its specified command.


Much appreciation if anyone can show me how to do the three things listed above, or alternative ways to accomplish the same objectives.

primo 12-01-2005 09:29 PM

find srcDir -name "*.log" | while read i ; do foobar "$i" ; done

The "" around *.log is important to prevent shell expansion before the find.

chrism01 12-01-2005 09:32 PM

Generally I'd use a loop. find can only exec external programs afaik, not shell fns, although maybe if you put the fn in another .sh file..

Try something like this:
Code:

for file in `find . -name '*.log' -print 2>/dev/null`
do
    echo $file
    echo "Dirname:"
    dirname $file
done

HTH

Dark_Helmet 12-01-2005 11:59 PM

Question 1:
Make a shell script that performs the function based on the first argument. You basically already have that from what you quoted above. Just make the file containing the function definition executable, and call that script instead of the functions. As in:
Code:

--- Start of my_script.sh
#!/bin/bash

Function1() {
    # This function takes one argument
    # blah blah blah
}

Function1 $1
--- End of my_script.sh

chmod u+x my_script.sh
find srcDir -name *.log -exec /path/to/my_script.sh {} \;

If the function definition is located in some other file (not meant to be used as a shell script - like .bashrc for instance), you could do this:
Code:

--- Start of my_script.sh
#!/bin/bash


source file_with_function_definition

Function1 $1
--- End of my_script.sh

chmod u+x my_script.sh
find srcDir -name *.log -exec /path/to/my_script.sh {} \;

Question 2:
Can't do what you want. The backticks are replaced before the command is executed. In other words, the substitution occurs before the find command starts. It does not happen for each file the find command locates. So find ... -exec `dirname {}` \; will have the backticks replaced with the command output immediately, making the command find ... -exec . \;. If you'd like to verify, run dirname {} on the command line and it will output a dot ( . ).

Question 3:
Can't do that either (as far as I know). xargs will only put the standard input onto the command line once. You would need to do something similar to the suggestion in #1. In other words create a shell script that intelligently handles multiple filenames. Something like:
Code:

--- Start of my_script.sh
#!/bin/bash

python pyScript $1 `dirname $1`/python.log
--- End of my_script.sh

However, keep in mind the script above would likely need to be run one-at-a-time. If you want multiple entries to run simulataneously (like having more than one "$1"-like argument) you'd have to take care of that by putting more intelligence in the script.

Also, the find command will allow you to use "{}" more than once. I've never had much use for it, but you can do things like this:
Code:

find . -maxdepth 1 -type f -exec echo {} {} \;
The find command will replace each occurrence of "{}" with the name of the matching file; you're not limited to just one.

thanhvn 12-02-2005 01:04 PM

Thanks to everyone who posted responses, I now have a much clearer understanding which enables me to do what I needed to do.


All times are GMT -5. The time now is 03:17 PM.