Вопрос или проблема
Я работаю с массивом заданий, где контролирую возможное выполнение различных шагов скрипта несколько раз. В этом случае только отсутствующие будут обработаны с помощью соответствующих операторов 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), при этом учитывая условные операторы для запуска определённых шагов только для отсутствующих папок и применения их именования, что требует некоторой хитрой логики работы со строками и массивами.
Общий план решения
- Использование массивов для хранения имен папок: Вам нужно будет создать массив, который будет хранить оригинальные и переименованные папки.
- Проверка существования папок: Условия
if
будут проверять, существует ли папка с переименованным именем, прежде чем выполнять последующие шаги. - Обновление списка имен: При каждом выполнении скрипта будет проверяться наличие папок, и логика будет переходить к обработке только тех папок, которые еще не были обработаны.
Пример реализации
Вот как может выглядеть ваш скрипт с учётом указанных выше моментов:
#!/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
: Эта функция принимает имя папки и проверяет, есть ли логи. Если логи уже существуют, процесс для данной папки не повторяется. В противном случае выполняются команды анализа и переименовывания папки. - Цикл обработки: Каждая папка из массива обрабатывается в соответствии с её состоянием, и при необходимости выполняются команды обработки.
Заключение
Итак, используя предложенный подход, можно эффективно управлять обработкой папок на основе существующих условий. Таким образом, условные операторы в вашем массиве задач дают возможность не только обрабатывать отсутствующие папки, но и учитывать изменения, происходящие в ходе выполнения скрипта.