Проблемы с переменной в скрипте Unix Shell - PullRequest
4 голосов
/ 10 августа 2009

У меня проблемы с передачей переменной из цикла.

Код:

# 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}"

Это всегда будет выводить 1. Любая идея, как сделать PROCESSED = 0?

Это делается на машине Solaris 9.

Ответы [ 4 ]

6 голосов
/ 10 августа 2009

Причина в том, что while -команда выполняется внутри канала, что означает, что она выполняется внутри под-оболочки, поэтому назначения переменных не передаются вызывающей оболочке.

Одним из решений является перенаправление ввода (может потребоваться сначала записать его во временный файл):

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

Другое решение - использовать стандартный вывод команды while для распространения значения PROCESSED:

PROCESSED=`find | while read f; do
    echo "Echo other stuff on stderr" >&2 
    echo 1
done`
0 голосов
/ 18 января 2013

Проблема в оболочке, которую вы используете. Если вы выполните sh, он не будет обрабатываться так, как вы хотите, но если вы выполните ksh, он будет работать.

0 голосов
/ 10 августа 2009

Вы можете использовать возвращаемое значение подоболочки для передачи информации этого типа в вызывающую оболочку:

#!/bin/sh

find $PROCESSED&#95;DIR -type f | {
    while read -r i; do
        cmp "$i" "$TMP&#95;TXT" &#62; /dev/null && exit 0;
    done;
    exit 1;
}
PROCESSED=$?
echo $PROCESSED

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

filename=$(find $PROCESSED&#95;DIR -type f | {
    while read -r i; do
        if cmp "$i" "$TMP&#95;TXT" &#62; /dev/null; then
            echo $i;
            exit 0;
        fi
    done;
    exit 1;
})
PROCESSED=$?
echo $PROCESSED: $filename

0 голосов
/ 10 августа 2009

Линия

PROCESSED=0

будет выполняться командой while как часть канала, а не оболочкой. Если вы вместо этого используете xargs и помещаете свой цикл while и сравнение в отдельный скрипт оболочки, который возвращает соответствующее возвращаемое значение, вы можете использовать

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

для обновления переменной PROCESSED в сценарии оболочки.

...