массив заданий с условными операторами

Вопрос или проблема

Я работаю с массивом заданий, где контролирую возможное выполнение различных шагов скрипта несколько раз. В этом случае только отсутствующие будут обработаны с помощью соответствующих операторов if.

В рамках скрипта мне нужно переименовать папки перед последней командой, так что я хочу, чтобы операторы if также проверяли вновь названные папки при последующих запусках; однако у меня отсутствует логика, как это сделать… Ниже приведен пример папок, которые я посещаю с массивом в первый раз.

/path/to/INLUP_00165
/path/to/INLUP_00169
/path/to/INLUP_00208
/path/to/INLUP_00214
/path/to/INLUP_00228
/path/to/INLUP_00245
/path/to/INLUP_00393
/path/to/INLUP_00418

Которые после первого выполнения станут следующими

/path/to/INLUP_00165-35
/path/to/INLUP_00169-27
/path/to/INLUP_00208-35
/path/to/INLUP_00214-32
/path/to/INLUP_00228-32
/path/to/INLUP_00245-34
/path/to/INLUP_00393-29
/path/to/INLUP_00418-32

Это скрипт, который я использую

#!/bin/bash
#SBATCH --nodes=1 --ntasks=1 --cpus-per-task=12
#SBATCH --time=200:00:00
#SBATCH --mem=80gb
#
#SBATCH --job-name=name1
#SBATCH --output=name_1.out
#SBATCH --array=[1-8]%8
#
#SBATCH --partition=bigmem
#SBATCH --exclude=node5

NAMES=$1
h=$(sed -n "$SLURM_ARRAY_TASK_ID"p $NAMES)

#load modules

ID="$(echo ${h}/*.fastq.gz | cut -f 1 -d '.' | sed 's#/path/to/INLUP_[0-9]\+/##')"
readarray -t cond < <(
    for filename in INLUP_00*
    do 
        printf "$filename \n" | sed 's#INLUP_[0-9]\+-##'
    done
)

prefix="${1:-run_}"
number=1
ext="txt"

newcount="${2:-1}"

printf -v num "%03d" "$number"
fname="$prefix$num.$ext"

while [ -e "$fname" ]; do
  number=$((number + 1))
  printf -v num "%03d" "$number"
  fname="$prefix$num.$ext"
done

while ((newcount--)); do
  touch "$h/$fname"
  ((! newcount)) && break;
  number=$((number + 1))
  printf -v num "%03d" "$number"
  fname="$prefix$num.$ext"
done

cd $h

...

if [ -s $h/log_param.txt ] || [ -s $h-${SUFFIX}/log_param.txt ]
    then
        echo "..."
    else
        first command tool &> $h/log.txt; find . -maxdepth 1 -type f,l -not -name '*.filt.fastq.gz' -not -name '*.txt' -not -name '*.bin' -delete

        HIGH=$(grep '\[M::ha_analyze_count\] highest\:' $h/log.txt | tail -1 | sed 's#\[M::ha_analyze_count\] highest\: count\[##' | sed 's#\] = [0-9]\+$##') #highest peak
        LOW=$(grep '\[M::ha_analyze_count\] lowest\:' $h/log.txt | tail -1 | sed 's#\[M::ha_analyze_count\] lowest\: count\[##' | sed 's#\] = [0-9]\+$##') #lowest peak
        SUFFIX="$(echo $(( ($HIGH - $LOW) "*" 3/4 + $LOW )))" #estimated homozygous coverage

        mv $h $h-${SUFFIX}

        HOM_COV="$(echo ${h} | sed 's#/path/to/INLUP_[0-9]\+-##')"

        last command tool &> $h-${SUFFIX}/log_param.txt
fi

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

readarray -t cond < <(
    for filename in INLUP_00*
    do 
        printf "$filename \n" | sed 's#INLUP_[0-9]\+-##'
    done
)

Как я могу связать это с файлом, который я подаю в качестве ввода, который остается неизменным и содержит оригинальные пути к папкам? Возможно, что-то связанное с тем, как путь ассоциируется с ИД ЗАДАЧИ, например здесь h=$(sed -n "$SLURM_ARRAY_TASK_ID"p $NAMES). Сообщите мне, спасибо заранее!

Ответ или решение

Условные операторы в массиве задач

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

Общий план решения

  1. Использование массивов для хранения имен папок: Вам нужно будет создать массив, который будет хранить оригинальные и переименованные папки.
  2. Проверка существования папок: Условия if будут проверять, существует ли папка с переименованным именем, прежде чем выполнять последующие шаги.
  3. Обновление списка имен: При каждом выполнении скрипта будет проверяться наличие папок, и логика будет переходить к обработке только тех папок, которые еще не были обработаны.

Пример реализации

Вот как может выглядеть ваш скрипт с учётом указанных выше моментов:

#!/bin/bash
#SBATCH --nodes=1 --ntasks=1 --cpus-per-task=12
#SBATCH --time=200:00:00
#SBATCH --mem=80gb
#SBATCH --job-name=name1
#SBATCH --output=name_1.out
#SBATCH --array=[1-8]%8
#SBATCH --partition=bigmem
#SBATCH --exclude=node5

NAMES=$1
h=$(sed -n "$SLURM_ARRAY_TASK_ID"p $NAMES)

# Функция для обработки папки
process_folder() {
    local folder=$1
    local suffix=$2
    # Проверяем логи
    if [ -s "$folder/log_param.txt" ] || [ -s "$folder-${suffix}/log_param.txt" ]; then
        echo "Обработка для $folder уже выполнена."
    else
        # Выполняем команду и обновляем логи
        first_command_tool &> "$folder/log.txt"
        # Анализируем логи для получения HIGH и LOW значений
        HIGH=$(grep '\[M::ha_analyze_count\] highest\:' "$folder/log.txt" | tail -1 | sed 's#\[M::ha_analyze_count\] highest\: count\[##;s#\] = [0-9]\+$##')
        LOW=$(grep '\[M::ha_analyze_count\] lowest\:' "$folder/log.txt" | tail -1 | sed 's#\[M::ha_analyze_count\] lowest\: count\[##;s#\] = [0-9]\+$##')
        SUFFIX=$(echo $(( (HIGH - LOW) * 3 / 4 + LOW )))

        # Переименовываем папку
        mv "$folder" "$folder-${SUFFIX}"

        last_command_tool &> "$folder-${SUFFIX}/log_param.txt"
    fi
}

# Чтение имен папок
readarray -t folders < <(sed 's#/path/to/\(INLUP_[0-9]\+\)#\1#' "$NAMES")

# Обработка папок
for folder in "${folders[@]}"; do
    # Извлекаем суффикс из имени папки
    if [[ "$folder" =~ INLUP_[0-9]+-([0-9]+) ]]; then
        suffix=${BASH_REMATCH[1]}
        process_folder "$h" "$suffix"
    else
        process_folder "$h" ""
    fi
done

Объяснение кода

  • Чтение массива имен папок: Мы используем readarray для создания массива, содержащего имена папок из файла, который вы передаете как аргумент. Мы также применяем sed, чтобы удалить ненужные части из строк.
  • Функция process_folder: Эта функция принимает имя папки и проверяет, есть ли логи. Если логи уже существуют, процесс для данной папки не повторяется. В противном случае выполняются команды анализа и переименовывания папки.
  • Цикл обработки: Каждая папка из массива обрабатывается в соответствии с её состоянием, и при необходимости выполняются команды обработки.

Заключение

Итак, используя предложенный подход, можно эффективно управлять обработкой папок на основе существующих условий. Таким образом, условные операторы в вашем массиве задач дают возможность не только обрабатывать отсутствующие папки, но и учитывать изменения, происходящие в ходе выполнения скрипта.

Оцените материал
Добавить комментарий

Капча загружается...