简体   繁体   中英

Problems with variable in Unix Shell script

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.

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`

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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM