Запустите команду только один раз в цикле for в Bash - PullRequest
0 голосов
/ 26 октября 2018

У меня есть следующий шаблон кода bash из функции:

for folder in ${FOLDER[@]}; do
    if [ $# -ne 0 ]; then
        rsync -rvh --delete-after ${folder} ${folder_dest}
    else
        local zipFile=$(stamp-files file.zip)
        unzip -q ${zipFile} "${folder}"*  -d "${folder_src}"
        rsync -rvh --delete-after ${folder_src}${folder} ${folder_dest}
        rsync -rvh --delete-after ${folder_src}${folder} ${folder_dest2}
    fi
done

Так что в этой функции у меня есть оператор if в цикле for.И как вы можете видеть в другой части, есть вызов другой функции stamp-files.Этот вызов других функций необходим только на первой итерации, и даже если он не вызывает каких-либо проблем, его можно определенно улучшить, просто вызвав его один раз.

Знаете ли вы, как я могу сделать это просто исохранить эту форму кода (оператор if в цикле for)?

Ответы [ 3 ]

0 голосов
/ 26 октября 2018

Если вам нужно сохранить структуру вашего цикла for и внутри, если:

unset stamp_files_done
for folder in ${FOLDER[@]}; do
    if [ $# -ne 0 ]; then
        rsync -rvh --delete-after ${folder} ${folder_dest}
    else
        if [[ -z ${stamp_files_done+x} ]]; then local files=$(stamp-files ${folder}); stamp_files_done=""; fi
        rsync -rvh --delete-after ${files} ${folder_dest}
    fi
done

Вы также можете объяснить общую задачу, чтобы иметь более точное решение.

0 голосов
/ 26 октября 2018

Я знаю, что вы сказали, что хотите сохранить форму кода, но стилистически я всегда не решаюсь структурировать код с if внутри цикла просто для обработки первого элемента массива - япредпочитайте поднимать код, чтобы подчеркнуть, что первый элемент обрабатывается специально.Другой вариант - добавить переменную состояния, которая никогда не делает код более понятным.

В вашем случае, как насчет

if [ ${#FOLDER[@]} -ne 0 ]; then
    local files=$(stamp-files ${FOLDER[0]})
    rsync -rvh --delete-after ${files} ${folder_dest}
    for folder in ${FOLDER[@]:1}; do
        rsync -rvh --delete-after ${folder} ${folder_dest}
    done
fi
0 голосов
/ 26 октября 2018

Вы можете установить переменную и изменить ее в первой итерации:

first='yes'
for folder in "{folders[@]}"; do
    if [[ $first == 'yes' ]]; then
        local files=$(stamp-files "$folder")
        rsync -rvh --delete-after "$files" "$folder_dest"
        first='no'
    else
        rsync -rvh --delete-after "$folder" "$folder_dest"
    fi
done

То, как вы пытались использовать $#, не сработало бы: это число позиционных параметров и не имеет ничего общегос номером итерации или аналогичным.

Я также изменил несколько вещей:

  • folders вместо FOLDER;имена переменных в верхнем регистре с большей вероятностью конфликтуют с переменными оболочки и окружения
  • Все расширения заключаются в кавычки для предотвращения разбиения и сглаживания слов (левая часть в [[...]] автоматически указывается в кавычках)
  • Я использую$folder вместо ${folder}, но на самом деле это просто личный вкус
...