2

I have a shell-script that looks like the following code snippet:

...
export updates=0

processFiles() {
    updates=$((updates+1))
}

export -f processFiles
find $path -exec /bin/bash -c "processFiles '{}'" \;

echo $updates

The use is to count the amount of updates, inserts and files to keep. Unfortunately the last echo always prints 0.

I have already tried to use export in the function as well - didn't work.

2
  • 2
    The variable updates is modified in a child process. The parent process will never see its modifications. Now tell us what you're trying to achieve, maybe there's another solution that will be more efficient than the one you're trying. Commented Dec 2, 2012 at 12:18
  • The goal is to print a little "statistic" after the script has finished. processFiles does either keep a file as is, insert a new one or update an existing one. After all files have been processed i want to know the number each operation took place. This statistic is printed after the find finished its duty, thus its not possible to do this in the processFiles function. Commented Dec 2, 2012 at 12:22

1 Answer 1

1

Instead of using find, you can use bash directly, provided your search criteria are simple enough. E.g.,

for file in *; do
    processFiles "$file"
done

will execute the function processFiles on all files and directories of the current directory (except the hidden ones) with argument the name of each file and directory. If you need to apply it recursively to all files and directories and subdirectories (except the hidden ones), use the globstar shell option:

#!/bin/bash

shopt -s globstar
shopt -s nullglob

updates=0

processFiles() {
    ((++updates))
}

for file in **; do
    processFiles "$file"
done

echo "$updates"

If you just want files, and no directories, insert this in the for loop:

    [[ -f "$file" ]] || continue

which will continue the loop if file is not a file (i.e., if it's something else, like a directory).

To match only files in a directory obtained by expanding the variable path, write your for loop thus:

for file in "$path"/*; do

(or "$path"/** if you're using globstar and want recursion).

If you need more complex search criteria, you can always use extglob option. If you need to also include the hidden files, use the dotglob option.

You'll find more info about bash in the reference manual, and in particular these sections:

One last note: If you really don't like this 100% bash solution and if you still want to do something along the script in your OP, then don't use bash variables, but use a (temporary) file instead to store the values you need to pass from one process to another. This is a cheap IPC method that works pretty well, but that is more difficult to implement safely.

Sign up to request clarification or add additional context in comments.

2 Comments

I really like that solution! There is now only one thing left: the for loop does start when the last file is found. Is it possible to modify this solution such that the function is performed right when the file is found (like find -exec does)?
@Lorunification I have no idea whether it's possible or not... in fact, I really doubt it's possible; but maybe someone cleverer will come up with a better (simple) solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.