|
|
|
|
@ -4,104 +4,120 @@
|
|
|
|
|
# Модуль основной логики: поиск файлов, сопоставление, генерация имён
|
|
|
|
|
#==============================================================================
|
|
|
|
|
|
|
|
|
|
# Глобальная переменная для хранения подготовленных данных
|
|
|
|
|
# Формат: "видео_файл\tаудио_файл\tвыходной_файл" для каждой строки
|
|
|
|
|
declare -a FILE_TRIPLETS
|
|
|
|
|
|
|
|
|
|
# Основная функция, которая находит и сопоставляет файлы
|
|
|
|
|
# Возвращает 0 в случае успеха, 1 в случае ошибки
|
|
|
|
|
# Функция стала "умной" и проверяет CURRENT_ACTION
|
|
|
|
|
logic_prepare_file_lists() {
|
|
|
|
|
# Очищаем предыдущие результаты
|
|
|
|
|
FILE_TRIPLETS=()
|
|
|
|
|
|
|
|
|
|
# Проверка, заданы ли все необходимые пути
|
|
|
|
|
if [[ -z "$VIDEO_SRC_DIR" || -z "$AUDIO_SRC_DIR" || -z "$OUTPUT_BASE_DIR" || -z "$OUTPUT_SERIES_NAME" ]]; then
|
|
|
|
|
ui_show_message "Ошибка" "Не все обязательные параметры заданы (каталоги видео, аудио, вывода и имя сериала)."
|
|
|
|
|
return 1
|
|
|
|
|
local common_params_ok=true
|
|
|
|
|
if [[ -z "$VIDEO_SRC_DIR" || -z "$OUTPUT_BASE_DIR" || -z "$OUTPUT_SERIES_NAME" ]]; then
|
|
|
|
|
common_params_ok=false
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# 1. Найти видеофайлы
|
|
|
|
|
# Использование `find ... -print0` и `mapfile` для безопасной обработки имён с пробелами
|
|
|
|
|
# 1. Находим видеофайлы (это нужно для обоих режимов)
|
|
|
|
|
local video_list_raw
|
|
|
|
|
mapfile -d '' video_list_raw < <(find "$VIDEO_SRC_DIR" -maxdepth 1 -name "$VIDEO_FILE_PATTERN" -print0 | sort -z)
|
|
|
|
|
if [ ${#video_list_raw[@]} -eq 0 ]; then
|
|
|
|
|
ui_show_message "Ошибка" "Видеофайлы по шаблону '$VIDEO_FILE_PATTERN' в каталоге '$VIDEO_SRC_DIR' не найдены."
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# 2. Найти аудиофайлы
|
|
|
|
|
# maxdepth не используется, чтобы искать в подкаталогах, как в примерах
|
|
|
|
|
local audio_list_raw
|
|
|
|
|
mapfile -d '' audio_list_raw < <(find "$AUDIO_SRC_DIR" -name "$AUDIO_FILE_PATTERN" -print0 | sort -z)
|
|
|
|
|
if [ ${#audio_list_raw[@]} -eq 0 ]; then
|
|
|
|
|
ui_show_message "Ошибка" "Аудиофайлы по шаблону '$AUDIO_FILE_PATTERN' в каталоге '$AUDIO_SRC_DIR' не найдены."
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# 3. Проверить совпадение количества файлов
|
|
|
|
|
if [ ${#video_list_raw[@]} -ne ${#audio_list_raw[@]} ]; then
|
|
|
|
|
local msg="Количество найденных файлов не совпадает!\n\n"
|
|
|
|
|
msg+="Видео: ${#video_list_raw[@]}\n"
|
|
|
|
|
msg+="Аудио: ${#audio_list_raw[@]}\n\n"
|
|
|
|
|
msg+="Проверьте каталоги и шаблоны поиска."
|
|
|
|
|
ui_show_message "Ошибка сопоставления" "$msg"
|
|
|
|
|
return 1
|
|
|
|
|
if $common_params_ok; then
|
|
|
|
|
mapfile -d '' video_list_raw < <(find "$VIDEO_SRC_DIR" -maxdepth 1 -name "$VIDEO_FILE_PATTERN" -print0 | sort -z)
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# 4. Сгенерировать выходные имена и собрать триплеты
|
|
|
|
|
local i
|
|
|
|
|
for i in "${!video_list_raw[@]}"; do
|
|
|
|
|
local video_file="${video_list_raw[$i]}"
|
|
|
|
|
local audio_file="${audio_list_raw[$i]}"
|
|
|
|
|
local video_basename
|
|
|
|
|
video_basename=$(basename "$video_file")
|
|
|
|
|
|
|
|
|
|
# Извлекаем номер эпизода с помощью regex
|
|
|
|
|
if [[ "$video_basename" =~ $EPISODE_NUMBER_REGEX ]]; then
|
|
|
|
|
local episode_num="${BASH_REMATCH[1]}"
|
|
|
|
|
# Приводим к формату с ведущим нулём, если нужно (например, 1 -> 01)
|
|
|
|
|
episode_num=$(printf "%02d" "$((10#$episode_num))")
|
|
|
|
|
else
|
|
|
|
|
ui_show_message "Ошибка Regex" "Не удалось извлечь номер эпизода из файла:\n$video_basename\n\nС помощью регулярного выражения:\n$EPISODE_NUMBER_REGEX"
|
|
|
|
|
# РЕЖИМ: СКЛЕЙКА
|
|
|
|
|
if [ "$CURRENT_ACTION" == "MERGE" ]; then
|
|
|
|
|
if ! $common_params_ok || [[ -z "$AUDIO_SRC_DIR" ]]; then
|
|
|
|
|
ui_show_message "Ошибка" "Для склейки должны быть заданы все каталоги (видео, аудио, вывод) и имя сериала."
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
if [ ${#video_list_raw[@]} -eq 0 ]; then
|
|
|
|
|
ui_show_message "Ошибка" "Видеофайлы по шаблону '$VIDEO_FILE_PATTERN' не найдены."
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Собираем имя выходного файла из шаблона
|
|
|
|
|
local output_name="$OUTPUT_FILENAME_TEMPLATE"
|
|
|
|
|
output_name="${output_name/\{SERIES_NAME\}/$OUTPUT_SERIES_NAME}"
|
|
|
|
|
output_name="${output_name/\{SEASON\}/$SEASON_NUMBER}"
|
|
|
|
|
output_name="${output_name/\{EPISODE\}/$episode_num}"
|
|
|
|
|
local audio_list_raw
|
|
|
|
|
mapfile -d '' audio_list_raw < <(find "$AUDIO_SRC_DIR" -name "$AUDIO_FILE_PATTERN" -print0 | sort -z)
|
|
|
|
|
if [ ${#audio_list_raw[@]} -eq 0 ]; then
|
|
|
|
|
ui_show_message "Ошибка" "Аудиофайлы по шаблону '$AUDIO_FILE_PATTERN' не найдены."
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
if [ ${#video_list_raw[@]} -ne ${#audio_list_raw[@]} ]; then
|
|
|
|
|
ui_show_message "Ошибка" "Количество видео (${#video_list_raw[@]}) и аудио (${#audio_list_raw[@]}) не совпадает."
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
local output_path="${OUTPUT_BASE_DIR}/${output_name}"
|
|
|
|
|
# Собираем триплеты
|
|
|
|
|
for i in "${!video_list_raw[@]}"; do
|
|
|
|
|
local video_file="${video_list_raw[$i]}"
|
|
|
|
|
local audio_file="${audio_list_raw[$i]}"
|
|
|
|
|
local output_path
|
|
|
|
|
output_path=$(logic_generate_output_name "$video_file") || return 1
|
|
|
|
|
FILE_TRIPLETS+=("$video_file"$'\t'"$audio_file"$'\t'"$output_path")
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
# РЕЖИМ: СИМЛИНКИ
|
|
|
|
|
elif [ "$CURRENT_ACTION" == "SYMLINK" ]; then
|
|
|
|
|
if ! $common_params_ok; then
|
|
|
|
|
ui_show_message "Ошибка" "Для симлинков должны быть заданы каталог видео, каталог вывода и имя сериала."
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
if [ ${#video_list_raw[@]} -eq 0 ]; then
|
|
|
|
|
ui_show_message "Ошибка" "Видеофайлы по шаблону '$VIDEO_FILE_PATTERN' не найдены."
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Сохраняем триплет в массив
|
|
|
|
|
FILE_TRIPLETS+=("$video_file"$'\t'"$audio_file"$'\t'"$output_path")
|
|
|
|
|
done
|
|
|
|
|
# Собираем пары (аудио-поле оставляем пустым)
|
|
|
|
|
for video_file in "${video_list_raw[@]}"; do
|
|
|
|
|
local output_path
|
|
|
|
|
output_path=$(logic_generate_output_name "$video_file") || return 1
|
|
|
|
|
FILE_TRIPLETS+=("$video_file"$'\t\t'"$output_path")
|
|
|
|
|
done
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Вспомогательная функция для генерации имени, чтобы не дублировать код
|
|
|
|
|
logic_generate_output_name() {
|
|
|
|
|
local video_file="$1"
|
|
|
|
|
local video_basename
|
|
|
|
|
video_basename=$(basename "$video_file")
|
|
|
|
|
|
|
|
|
|
# Функция для отображения предпросмотра
|
|
|
|
|
logic_show_preview() {
|
|
|
|
|
if ! logic_prepare_file_lists; then
|
|
|
|
|
# Сообщение об ошибке уже было показано внутри logic_prepare_file_lists
|
|
|
|
|
if [[ "$video_basename" =~ $EPISODE_NUMBER_REGEX ]]; then
|
|
|
|
|
local episode_num
|
|
|
|
|
episode_num=$(printf "%02d" "$((10#${BASH_REMATCH[1]}))")
|
|
|
|
|
|
|
|
|
|
local output_name="$OUTPUT_FILENAME_TEMPLATE"
|
|
|
|
|
output_name="${output_name/\{SERIES_NAME\}/$OUTPUT_SERIES_NAME}"
|
|
|
|
|
output_name="${output_name/\{SEASON\}/$SEASON_NUMBER}"
|
|
|
|
|
output_name="${output_name/\{EPISODE\}/$episode_num}"
|
|
|
|
|
|
|
|
|
|
echo "${OUTPUT_BASE_DIR}/${output_name}"
|
|
|
|
|
return 0
|
|
|
|
|
else
|
|
|
|
|
ui_show_message "Ошибка Regex" "Не удалось извлечь номер эпизода из файла:\n$video_basename\n\nС помощью регулярного выражения:\n$EPISODE_NUMBER_REGEX"
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Предпросмотр тоже адаптируется к режиму
|
|
|
|
|
logic_show_preview() {
|
|
|
|
|
if ! logic_prepare_file_lists; then return 1; fi
|
|
|
|
|
if [ ${#FILE_TRIPLETS[@]} -eq 0 ]; then
|
|
|
|
|
ui_show_message "Предпросмотр" "Нет файлов для обработки."
|
|
|
|
|
ui_show_message "Предпросмотр" "Нет файлов для обработки по текущим настройкам."
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
local preview_text="Будут обработаны следующие файлы (${#FILE_TRIPLETS[@]} шт.):\n\n"
|
|
|
|
|
local preview_text="РЕЖИМ: $CURRENT_ACTION\nБудут обработаны следующие файлы (${#FILE_TRIPLETS[@]} шт.):\n\n"
|
|
|
|
|
local count=1
|
|
|
|
|
for triplet in "${FILE_TRIPLETS[@]}"; do
|
|
|
|
|
IFS=$'\t' read -r video audio output <<< "$triplet"
|
|
|
|
|
preview_text+="$(printf "%02d" $count). \n"
|
|
|
|
|
preview_text+=" \ZbВИДЕО:\Zn $(basename "$video")\n"
|
|
|
|
|
preview_text+=" \ZbАУДИО:\Zn $(basename "$audio")\n"
|
|
|
|
|
preview_text+=" \Zb-> ВЫВОД:\Zn $(basename "$output")\n\n"
|
|
|
|
|
|
|
|
|
|
if [ "$CURRENT_ACTION" == "MERGE" ]; then
|
|
|
|
|
preview_text+=" \ZbВИДЕО:\Zn $(basename "$video")\n"
|
|
|
|
|
preview_text+=" \ZbАУДИО:\Zn $(basename "$audio")\n"
|
|
|
|
|
preview_text+=" \Zb-> ВЫВОД:\Zn $(basename "$output")\n\n"
|
|
|
|
|
else # SYMLINK
|
|
|
|
|
preview_text+=" \ZbИСТОЧНИК:\Zn $(basename "$video")\n"
|
|
|
|
|
preview_text+=" \Zb-> ССЫЛКА:\Zn $(basename "$output")\n\n"
|
|
|
|
|
fi
|
|
|
|
|
((count++))
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
|