Bash В то время как цикл чтения файла за строкой завершается на определенной строке

Я пишу простой скрипт Bash, который просто вызывает HadnBrakeCli для рендеринга видео. Я также реализовал простую опцию очереди: файл очереди просто хранит строку-команду, которую он должен вызвать, чтобы начать рендеринг. Поэтому я написал цикл while, чтобы читать по одной строке за раз, оценивать $line и повторять до тех пор, пока файл не закончится.

          if [[ ${QUEUE_MODE} = 'RUN' ]]; then
    QUEUE_LEN=`cat ${CONFIG_DIR}/queue | wc -l`
    QUEUE_POS='1'
    printf "Queue lenght:\t ${QUEUE_LEN}\n"

    while IFS= read line; do
        echo "--Running render ${QUEUE_POS} on ${QUEUE_LEN}..."
        echo "++" && echo "$line" && echo "++"
        eval "${line}"
        tail -n +2 "${CONFIG_DIR}/queue" > "${CONFIG_DIR}/queue.tmp" && mv "${CONFIG_DIR}/queue.tmp" "${CONFIG_DIR}/queue"
        echo "--Render ended"
        QUEUE_POS=`expr $QUEUE_POS + 1`
    done < "${CONFIG_DIR}/queue"
    exit 0

Проблема в том, что любая команда заставляет цикл работать нормально (пустая строка, эхо "тест"...), но как только загружается правильный рендер, он запускается и завершается правильно, но циклы тоже существуют.

Я новичок, поэтому я попробовал некоторые незначительные изменения, чтобы увидеть, какой эффект я получил, но ничего не изменило результат. Я прокомментировал команду tail -n +2 "${CONFIG_DIR}/queue" > "${CONFIG_DIR}/queue.tmp" && mv "${CONFIG_DIR}/queue.tmp" "${CONFIG_DIR}/queue"или я добавил/убрал IFS=в цикле while или удалить -rв readкоманда. Извините, если вопрос тривиален, но мне действительно не хватает какой-то важной части того, как это работает, поэтому я даже не знаю, как искать решение.

Я положу образец общего рендера в файл очереди. HandBrakeCLI -i "/home/andrea/Videos/done/Rap dottor male e mini me.mp4" -o "/hdd/Render/Output/Rap dottor male e mini me.mkv" -e x265 -q 23 --encoder-preset faster --all-audio -E av_aac -6 dpl2 --all-subtitles -x pmode:pools='16' --verbose=0 2>/dev/null

1 ответ

читает из стандартного ввода, который крадет остальную часть файла очереди перед могу это увидеть. Мое любимое решение — передать файл не через стандартный ввод, например через файловый дескриптор №3:

      ...
while IFS= read line <&3; do    # The <&3 makes it read from FD #3
    ...
done 3< "${CONFIG_DIR}/queue"   # The 3< redirects the file into FD #3

Другой способ избежать этой проблемы — перенаправить ввод в команду HandBrakeCLI:

      ...
eval "${line}" </dev/null
...

В BashFAQ #89 есть дополнительная информация об этом: я читаю файл построчно и запускаю ssh или ffmpeg, обрабатывается только первая строка!

Кроме того, я не уверен, что доверяю тому, как вы используете для удаления строк из файла очереди по мере их выполнения. Я не уверен, что это действительно неправильно , просто мне это кажется хрупким. Кроме того, я бы рекомендовал использовать имена переменных в нижнем или смешанном регистре, поскольку существует множество имен, написанных заглавными буквами и имеющих особое значение, и повторное использование одного из них по ошибке может иметь странные последствия. Наконец, я бы порекомендовал запустить ваш скрипт через shellcheck.net, так как он даст некоторые другие хорошие рекомендации.

[Кстати, этот вопрос является дубликатом «Bash script делает цикл, выходящий раньше» , но у него нет ни одобренных, ни принятых ответов.]

Другие вопросы по тегам