4

I have trouble passing a variable from inside a loop.

Code:

# find all output.txt that has been modified last 24h ...
PROCESSED=1
find ${PROCESSED_DIR} -mtime -1 -name "output.txt" | while read i
do
    # .. and compare those with TMP_TXT
    if diff $i ${TMP_TXT} > /dev/null   
    then
        # If both are same EXIT search loop 
        PROCESSED=0
        exit
    fi
done
echo "PROCESSED=${PROCESSED}"

This will always output 1. Any idea how to make PROCESSED=0 ?

This is done on a Solaris 9 machine.

4 Answers 4

6

The reason is that the while-command is run inside a pipe which means that it is running inside a sub-shell, so variable assignments are not propagated to the calling shell.

One solution is to redirect the input (you may need to write it to a temporary file first):

while read f; do
    ...
done < foo.tmp

Another solution is to use the stdout from the while-command to propagate the value of PROCESSED:

PROCESSED=`find | while read f; do
    echo "Echo other stuff on stderr" >&2 
    echo 1
done`
Sign up to request clarification or add additional context in comments.

Comments

0

The line

PROCESSED=0

will be executed by the while command as part of the pipe, and not by the shell. If you instead use xargs and put your while loop and comparison into a separate shell script which returns an appropriate return value you can use

find ${PROCESSED_DIR} -mtime -1 -name "output.txt" | xargs -n1 your_compare_script.sh && PROCESSED=0

in order to update the PROCESSED variable in the shell script.

Comments

0

You can use the return value of the subshell to pass this type of information to the calling shell:

#!/bin/sh

find $PROCESSED_DIR -type f | {
    while read -r i; do
        cmp "$i" "$TMP_TXT" > /dev/null && exit 0;
    done;
    exit 1;
}
PROCESSED=$?
echo $PROCESSED

# or, if you want to detect the filename as well:

filename=$(find $PROCESSED_DIR -type f | {
    while read -r i; do
        if cmp "$i" "$TMP_TXT" > /dev/null; then
            echo $i;
            exit 0;
        fi
    done;
    exit 1;
})
PROCESSED=$?
echo $PROCESSED: $filename

Comments

0

The problem is the shell that you are using. If you do sh , it will not process the way you want but if you do ksh , it will work.

1 Comment

Welcome to SO. Thanks for your reply, but it would be really helpful for other users if you can provide with some code or links to make your answer more correct!

Your Answer

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