init
This commit is contained in:
Binary file not shown.
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
ROOTPATH="/var/www/nextcloud/data/grayhook/files/"
|
||||||
|
INDIR="Torrents"
|
||||||
|
OUTDIR="Archive/Anime"
|
||||||
|
ORIGNAME="Dandadan [WEB-DL CR 1080p AVC DDP]"
|
||||||
|
NAME="Dan Da Dan"
|
||||||
|
OUTPUTPATH="${ROOTPATH}/${OUTDIR}/${NAME}"
|
||||||
|
INPUTPATH="${ROOTPATH}/${INDIR}/${ORIGNAME}"
|
||||||
|
|
||||||
|
mkdir -p "${ROOTPATH}/${OUTDIR}/${NAME}" || exit -1;
|
||||||
|
paste -d '\n' \
|
||||||
|
<(find "$INPUTPATH" -maxdepth 1 -name '*.mkv' | sort) \
|
||||||
|
<(find "$INPUTPATH" -name '*AniLibria*.mka' | sort) \
|
||||||
|
<(find "$INPUTPATH" -maxdepth 1 -name '*.mkv' | sort | \
|
||||||
|
sed -e "s/.* \([0-9]\{2\}\) .*/${OUTPUTPATH//\//\\\/}\/${NAME} s01e\1.mkv/g") | \
|
||||||
|
xargs -d '\n' printf '"%s" "%s" "%s"\n' | \
|
||||||
|
xargs -n 3 \
|
||||||
|
ffmpeg_add_audio_into_video \
|
||||||
|
;
|
||||||
Executable
+30
@@ -0,0 +1,30 @@
|
|||||||
|
ROOTPATH="/var/www/nextcloud/data/grayhook/files/"
|
||||||
|
INDIR="Torrents"
|
||||||
|
OUTDIR="Archive/Anime"
|
||||||
|
ORIGNAME="Kimetsu.no.Yaiba.Hashira.Geiko.hen.WEB-DL.1080p"
|
||||||
|
NAME="Kimetsu no Yaiba Hashira Training"
|
||||||
|
OUTPUTPATH="${ROOTPATH}/${OUTDIR}/${NAME}"
|
||||||
|
INPUTPATH="${ROOTPATH}/${INDIR}/${ORIGNAME}"
|
||||||
|
|
||||||
|
[ -e "${ROOTPATH}/${OUTDIR}/${NAME}" ] || exit -1;
|
||||||
|
paste -d '\n' \
|
||||||
|
<(find "$INPUTPATH" -maxdepth 1 -name '*.mkv' | sort) \
|
||||||
|
<(find "$INPUTPATH/RUS Sound/StudioBand" -name '*.mka' | sort) \
|
||||||
|
<(find "$INPUTPATH" -maxdepth 1 -name '*.mkv' | sort | \
|
||||||
|
sed -e "s/.* \([0-9]\{2\}\) .*/${OUTPUTPATH//\//\\\/}\/${NAME} s05e\1.mkv/g") | \
|
||||||
|
xargs -d '\n' printf '"%s" "%s" "%s"\n' | \
|
||||||
|
xargs -n 3 \
|
||||||
|
ffmpeg_add_audio_into_video -d \
|
||||||
|
;
|
||||||
|
|
||||||
|
read || exit 1;
|
||||||
|
|
||||||
|
paste -d '\n' \
|
||||||
|
<(find "$INPUTPATH" -maxdepth 1 -name '*.mkv' | sort) \
|
||||||
|
<(find "$INPUTPATH/RUS Sound/StudioBand" -name '*.mka' | sort) \
|
||||||
|
<(find "$INPUTPATH" -maxdepth 1 -name '*.mkv' | sort | \
|
||||||
|
sed -e "s/.* \([0-9]\{2\}\) .*/${OUTPUTPATH//\//\\\/}\/${NAME} s05e\1.mkv/g") | \
|
||||||
|
xargs -d '\n' printf '"%s" "%s" "%s"\n' | \
|
||||||
|
xargs -n 3 \
|
||||||
|
ffmpeg_add_audio_into_video \
|
||||||
|
;
|
||||||
Executable
+8
@@ -0,0 +1,8 @@
|
|||||||
|
DIRPATH="/var/www/nextcloud/data/grayhook/files/Torrents/Kimetsu.no.Yaiba.Katanakaji.no.Sato.hen.WEB-DL.1080p"
|
||||||
|
PRENAME="[SubsPlease] Kimetsu no Yaiba - Katanakaji no Sato-hen - "
|
||||||
|
POSTNAME=" [1080p]"
|
||||||
|
SOUNDDIR="RUS Sound/StudioBand"
|
||||||
|
for x in {0..11}; do
|
||||||
|
ffmpeg_add_audio_into_video "$DIRPATH/$PRENAME`printf "%02d" $x`$POSTNAME.mkv" \
|
||||||
|
"$DIRPATH/$SOUNDDIR/$PRENAME`printf "%02d" $x`$POSTNAME.mka";
|
||||||
|
done
|
||||||
Executable
+19
@@ -0,0 +1,19 @@
|
|||||||
|
ROOTPATH="/var/www/nextcloud/data/grayhook/files/"
|
||||||
|
INDIR="Torrents"
|
||||||
|
OUTDIR="Archive/Anime"
|
||||||
|
ORIGNAME="Hunter x Hunter [6][BD 720] TV2"
|
||||||
|
NAME="Hunter x Hunter"
|
||||||
|
SED_NUMBER='s/-_\([0-9]\{3\}\)_/ \1 /g'
|
||||||
|
OUTPUTPATH="${ROOTPATH}/${OUTDIR}/${NAME}"
|
||||||
|
INPUTPATH="${ROOTPATH}/${INDIR}/${ORIGNAME}"
|
||||||
|
|
||||||
|
mkdir -p "${ROOTPATH}/${OUTDIR}/${NAME}" || exit -1;
|
||||||
|
paste -d '\n' \
|
||||||
|
<(find "$INPUTPATH" -name '*.mkv' | sort) \
|
||||||
|
<(find "$INPUTPATH/Rus Audio/JAM" -name '*.ac3' | sort) \
|
||||||
|
<(find "$INPUTPATH" -name '*.mkv' | sort | \
|
||||||
|
sed -e "s/.*-_\([0-9]\{3\}\)_.*/${OUTPUTPATH//\//\\\/}\/${NAME} s01e\1.mkv/g") | \
|
||||||
|
xargs -d '\n' printf '"%s" "%s" "%s"\n' | \
|
||||||
|
xargs -n 3 \
|
||||||
|
ffmpeg_add_audio_into_video \
|
||||||
|
;
|
||||||
Executable
+19
@@ -0,0 +1,19 @@
|
|||||||
|
ROOTPATH="/var/www/nextcloud/data/grayhook/files/"
|
||||||
|
INDIR="Torrents"
|
||||||
|
OUTDIR="Archive/Anime"
|
||||||
|
ORIGNAME="MASHLE Season 2 [2024][WEB-DL][1080p]"
|
||||||
|
NAME="MASHLE: MAGIC AND MUSCLES"
|
||||||
|
SED_NUMBER='s/ \([0-9]\{2\}\) / 0\1 /g'
|
||||||
|
OUTPUTPATH="${ROOTPATH}/${OUTDIR}/${NAME}"
|
||||||
|
INPUTPATH="${ROOTPATH}/${INDIR}/${ORIGNAME}"
|
||||||
|
|
||||||
|
mkdir -p "${ROOTPATH}/${OUTDIR}/${NAME}" || exit -1;
|
||||||
|
paste -d '\n' \
|
||||||
|
<(find "$INPUTPATH" -name '*.mkv' | sort) \
|
||||||
|
<(find "$INPUTPATH" -name '*Anilibria*.mka' | sort) \
|
||||||
|
<(find "$INPUTPATH" -name '*.mkv' | sort | \
|
||||||
|
sed -e "s/.* \([0-9]\{2\}\) .*/${OUTPUTPATH//\//\\\/}\/${NAME} s02e\1.mkv/g") | \
|
||||||
|
xargs -d '\n' printf '"%s" "%s" "%s"\n' | \
|
||||||
|
xargs -n 3 \
|
||||||
|
ffmpeg_add_audio_into_video \
|
||||||
|
;
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
ROOTPATH="/var/www/nextcloud/data/grayhook/files/"
|
||||||
|
INDIR="Torrents"
|
||||||
|
OUTDIR="Archive/Anime"
|
||||||
|
ORIGNAME="[Kawaiika-Raws] (2020) Ishuzoku Reviewers [BDRip 1920x1080 HEVC FLAC]"
|
||||||
|
NAME="Interspecies Reviewers"
|
||||||
|
OUTPUTPATH="${ROOTPATH}/${OUTDIR}/${NAME}"
|
||||||
|
INPUTPATH="${ROOTPATH}/${INDIR}/${ORIGNAME}"
|
||||||
|
|
||||||
|
mkdir -p "${ROOTPATH}/${OUTDIR}/${NAME}" || exit -1;
|
||||||
|
paste -d '\n' \
|
||||||
|
<(find "$INPUTPATH" -maxdepth 1 -name '*.mkv' | sort) \
|
||||||
|
<(find "$INPUTPATH" -name '*Wakanim*.mka' | sort) \
|
||||||
|
<(find "$INPUTPATH" -maxdepth 1 -name '*.mkv' | sort | \
|
||||||
|
sed -e "s/.* \([0-9]\{2\}\) .*/${OUTPUTPATH//\//\\\/}\/${NAME} s01e\1.mkv/g") | \
|
||||||
|
xargs -d '\n' printf '"%s" "%s" "%s"\n' | \
|
||||||
|
xargs -n 3 \
|
||||||
|
ffmpeg_add_audio_into_video \
|
||||||
|
;
|
||||||
Executable
+19
@@ -0,0 +1,19 @@
|
|||||||
|
ROOTPATH="/var/www/nextcloud/data/grayhook/files/"
|
||||||
|
INDIR="Torrents"
|
||||||
|
OUTDIR="Archive/Anime"
|
||||||
|
#ORIGNAME="[Beatrice-Raws] Re.Zero - 2nd Season [BDRip 1080p HEVC TrueHD]"
|
||||||
|
ORIGNAME="[Beatrice-Raws] Re.Zero - 2nd Season - Part 2 [BDRip 1080p x265 Dolby TrueHD]"
|
||||||
|
NAME="Re ZERO Starting Life in Another World"
|
||||||
|
OUTPUTPATH="${ROOTPATH}/${OUTDIR}/${NAME}"
|
||||||
|
INPUTPATH="${ROOTPATH}/${INDIR}/${ORIGNAME}"
|
||||||
|
|
||||||
|
[ -e "${ROOTPATH}/${OUTDIR}/${NAME}" ] || exit -1;
|
||||||
|
paste -d '\n' \
|
||||||
|
<(find "$INPUTPATH" -maxdepth 1 -name '*.mkv' | sort) \
|
||||||
|
<(find "$INPUTPATH/Sounds/Crunchyroll" -name '*.mka' | sort) \
|
||||||
|
<(find "$INPUTPATH" -maxdepth 1 -name '*.mkv' | sort | \
|
||||||
|
sed -e "s/.* \([0-9]\{2\}\) .*/${OUTPUTPATH//\//\\\/}\/${NAME} s02e\1.mkv/g") | \
|
||||||
|
xargs -d '\n' printf '"%s" "%s" "%s"\n' | \
|
||||||
|
xargs -n 3 \
|
||||||
|
ffmpeg_add_audio_into_video \
|
||||||
|
;
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
ROOTPATH="/var/www/nextcloud/data/grayhook/files/"
|
||||||
|
INDIR="Torrents"
|
||||||
|
OUTDIR="Archive/Series"
|
||||||
|
ORIGNAME="Young Sheldon (Season 4) WEB-DL 1080p"
|
||||||
|
NAME="Young Sheldon S4"
|
||||||
|
OUTPUTPATH="${ROOTPATH}/${OUTDIR}/${NAME}"
|
||||||
|
INPUTPATH="${ROOTPATH}/${INDIR}/${ORIGNAME}"
|
||||||
|
|
||||||
|
[ -e "${OUTPUTPATH}" ] || { echo "$OUTPUTPATH does not exist"; exit -1; }
|
||||||
|
paste -d '\n' \
|
||||||
|
<(find "$INPUTPATH" -maxdepth 1 -name '*.mkv' | sort) \
|
||||||
|
<(find "${ROOTPATH}/${INDIR}/Young.Sheldon.2021.S04.1080p.(Kurazh-Bambej)" -name '*.mkv' | sort) \
|
||||||
|
<(find "$INPUTPATH" -maxdepth 1 -name '*.mkv' | sort | \
|
||||||
|
sed -e "s/.*S04E\([0-9]\{2\}\).*/${OUTPUTPATH//\//\\\/}\/${NAME} s04e\1.mkv/g") | \
|
||||||
|
xargs -d '\n' printf '"%s" "%s" "%s"\n' | \
|
||||||
|
xargs -n 3 \
|
||||||
|
ffmpeg_add_audio_into_video \
|
||||||
|
;
|
||||||
Executable
+19
@@ -0,0 +1,19 @@
|
|||||||
|
ROOTPATH="/var/www/nextcloud/data/grayhook/files/"
|
||||||
|
INDIR="Torrents"
|
||||||
|
OUTDIR="Archive/Anime"
|
||||||
|
#ORIGNAME="[Kawaiika-Raws] (2016) KonoSuba S1 [BDRip 1920x1080 HEVC FLAC]"
|
||||||
|
ORIGNAME="[Kawaiika-Raws] (2017) KonoSuba S2 [BDRip 1920x1080 HEVC FLAC]"
|
||||||
|
NAME="KonoSuba"
|
||||||
|
OUTPUTPATH="${ROOTPATH}/${OUTDIR}/${NAME}"
|
||||||
|
INPUTPATH="${ROOTPATH}/${INDIR}/${ORIGNAME}"
|
||||||
|
|
||||||
|
[ -e "${ROOTPATH}/${OUTDIR}/${NAME}" ] || exit -1;
|
||||||
|
paste -d '\n' \
|
||||||
|
<(find "$INPUTPATH" -maxdepth 1 -name '*.mkv' | sort) \
|
||||||
|
<(find "$INPUTPATH/RUS Sound" -name '*crunchyroll*.mka' | sort) \
|
||||||
|
<(find "$INPUTPATH" -maxdepth 1 -name '*.mkv' | sort | \
|
||||||
|
sed -e "s/.*S2E\([0-9]\{2\}\) .*/${OUTPUTPATH//\//\\\/}\/${NAME} s02e\1.mkv/g") | \
|
||||||
|
xargs -d '\n' printf '"%s" "%s" "%s"\n' | \
|
||||||
|
xargs -n 3 \
|
||||||
|
ffmpeg_add_audio_into_video \
|
||||||
|
;
|
||||||
Executable
+12
@@ -0,0 +1,12 @@
|
|||||||
|
DIRPATH="/var/www/nextcloud/data/grayhook/files/Torrents/"
|
||||||
|
VIDEODIR="Tokyo Ghoul/Tokyo Ghoul "
|
||||||
|
AUDIODIR="Tokyo Ghoul [BD] [720p]/"
|
||||||
|
OUTPUTPATH="/var/www/nextcloud/data/grayhook/files/Archive/Anime/Tokyo Ghoul TV-1 2014/Tokyo Ghoul S1E"
|
||||||
|
PRENAME="[Winter] Tokyo Ghoul "
|
||||||
|
POSTNAME=" [BDrip 1280x720 x264 Vorbis]"
|
||||||
|
SOUNDDIR="$AUDIODIR/RUS Sound/[JAM & Oriko]"
|
||||||
|
for x in {2..12}; do
|
||||||
|
ffmpeg_add_audio_into_video "$DIRPATH/$VIDEODIR`printf "%d" $x`.mkv" \
|
||||||
|
"$DIRPATH/$SOUNDDIR/$PRENAME`printf "%02d" $x`$POSTNAME.mka" \
|
||||||
|
"$OUTPUTPATH`printf "%02d" $x`.mkv";
|
||||||
|
done
|
||||||
Executable
+12
@@ -0,0 +1,12 @@
|
|||||||
|
DIRPATH="/var/www/nextcloud/data/grayhook/files/Torrents/"
|
||||||
|
VIDEODIR="Tokyo Ghoul Re"
|
||||||
|
AUDIODIR="Tokyo Ghoul Re"
|
||||||
|
OUTPUTPATH="/var/www/nextcloud/data/grayhook/files/Archive/Anime/Tokyo Ghoul TV-3 2018/Tokyo Ghoul S3E"
|
||||||
|
PRENAME="[anti-raws]Tokyo Ghoul Re ep."
|
||||||
|
POSTNAME="[BDRemux]"
|
||||||
|
SOUNDDIR="$AUDIODIR/RUS Sound/[JAM Club]"
|
||||||
|
for x in {1..12}; do
|
||||||
|
ffmpeg_add_audio_into_video "$DIRPATH/$VIDEODIR/$PRENAME`printf "%02d" $x`$POSTNAME.mkv" \
|
||||||
|
"$DIRPATH/$SOUNDDIR/$PRENAME`printf "%02d" $x`$POSTNAME.JAM Club.mka" \
|
||||||
|
"$OUTPUTPATH`printf "%02d" $x`.mkv";
|
||||||
|
done
|
||||||
Executable
+12
@@ -0,0 +1,12 @@
|
|||||||
|
DIRPATH="/var/www/nextcloud/data/grayhook/files/Torrents/"
|
||||||
|
VIDEODIR="Tokyo Ghoul Re S2"
|
||||||
|
AUDIODIR="Tokyo Ghoul Re S2"
|
||||||
|
OUTPUTPATH="/var/www/nextcloud/data/grayhook/files/Archive/Anime/Tokyo Ghoul TV-4 2018/Tokyo Ghoul S4E"
|
||||||
|
PRENAME="[anti-raws]Tokyo Ghoul Re S2 ep."
|
||||||
|
POSTNAME="[BDRemux]"
|
||||||
|
SOUNDDIR="$AUDIODIR/RUS Sound/[JAM Club]"
|
||||||
|
for x in {1..12}; do
|
||||||
|
ffmpeg_add_audio_into_video "$DIRPATH/$VIDEODIR/$PRENAME`printf "%02d" $x`$POSTNAME.mkv" \
|
||||||
|
"$DIRPATH/$SOUNDDIR/$PRENAME`printf "%02d" $x`$POSTNAME.JAM Club.mka" \
|
||||||
|
"$OUTPUTPATH`printf "%02d" $x`.mkv";
|
||||||
|
done
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
DIRPATH="/var/www/nextcloud/data/grayhook/files/Torrents/"
|
||||||
|
VIDEODIR="Tokyo Ghoul Root A"
|
||||||
|
AUDIODIR="Tokyo Ghoul Root A"
|
||||||
|
OUTPUTPATH="/var/www/nextcloud/data/grayhook/files/Archive/Anime/Tokyo Ghoul TV-2 2015/Tokyo Ghoul S2E"
|
||||||
|
PRENAME="[anti-raws]Tokyo Ghoul Root A ep."
|
||||||
|
POSTNAME="[BDRemux]"
|
||||||
|
SOUNDDIR="$AUDIODIR/RUS Sound/[JAM & Nika Lenina]"
|
||||||
|
for x in {11..12}; do
|
||||||
|
ffmpeg_add_audio_into_video "$DIRPATH/$VIDEODIR/$PRENAME`printf "%02d" $x`$POSTNAME.mkv" \
|
||||||
|
"$DIRPATH/$SOUNDDIR/$PRENAME`printf "%02d" $x`$POSTNAME.JAM & Nika Lenina.mka" \
|
||||||
|
"$OUTPUTPATH`printf "%02d" $x`.mkv";
|
||||||
|
done
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#==============================================================================
|
||||||
|
# Модуль действий: выполнение mkvmerge, создание симлинков и т.д.
|
||||||
|
#==============================================================================
|
||||||
|
|
||||||
|
# Функция для склейки видео и аудио
|
||||||
|
# $1: Исходный видеофайл
|
||||||
|
# $2: Исходный аудиофайл
|
||||||
|
# $3: Выходной файл
|
||||||
|
action_merge_mkv() {
|
||||||
|
local video_file="$1"
|
||||||
|
local audio_file="$2"
|
||||||
|
local output_file="$3"
|
||||||
|
|
||||||
|
echo "---"
|
||||||
|
echo "ИСХОДНОЕ ВИДЕО : $video_file"
|
||||||
|
echo "ИСХОДНОЕ АУДИО : $audio_file"
|
||||||
|
echo "РЕЗУЛЬТАТ : $output_file"
|
||||||
|
|
||||||
|
# Это основная команда. Вы можете настроить ее под себя.
|
||||||
|
# --language 0:und - язык первой дорожки (видео) - неопределенный
|
||||||
|
# --language 1:rus - язык второй дорожки (аудио) - русский
|
||||||
|
# Вы можете добавить больше опций, например, --track-name, --default-track-flag
|
||||||
|
mkvmerge \
|
||||||
|
-o "$output_file" \
|
||||||
|
--language 0:und "$video_file" \
|
||||||
|
--language 1:rus "$audio_file"
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "УСПЕХ: Файл создан."
|
||||||
|
else
|
||||||
|
echo "ОШИБКА: mkvmerge завершился с ошибкой."
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Функция для создания символической ссылки
|
||||||
|
# $1: Исходный видеофайл
|
||||||
|
# $2: Имя ссылки (выходной файл)
|
||||||
|
action_create_symlink() {
|
||||||
|
local video_file="$1"
|
||||||
|
local output_file="$2"
|
||||||
|
|
||||||
|
echo "---"
|
||||||
|
echo "ИСТОЧНИК: $video_file"
|
||||||
|
echo "ССЫЛКА : $output_file"
|
||||||
|
|
||||||
|
# Создаем символическую ссылку
|
||||||
|
ln -s "$video_file" "$output_file"
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "УСПЕХ: Ссылка создана."
|
||||||
|
else
|
||||||
|
echo "ОШИБКА: Не удалось создать ссылку."
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Главная функция запуска обработки
|
||||||
|
run_processing() {
|
||||||
|
# 1. Готовим списки файлов
|
||||||
|
if ! logic_prepare_file_lists; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${#FILE_TRIPLETS[@]} -eq 0 ]; then
|
||||||
|
ui_show_message "Запуск" "Нет файлов для обработки."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2. Спрашиваем, что делать
|
||||||
|
local action_to_perform
|
||||||
|
action_to_perform=$(ui_select_action)
|
||||||
|
|
||||||
|
if [[ -z "$action_to_perform" ]]; then
|
||||||
|
ui_show_message "Отмена" "Операция отменена пользователем."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. Финальное подтверждение
|
||||||
|
local confirmation_text="Вы уверены, что хотите выполнить '${action_to_perform}' для ${#FILE_TRIPLETS[@]} файлов?\n\n"
|
||||||
|
confirmation_text+="Результаты будут сохранены в:\n$OUTPUT_BASE_DIR"
|
||||||
|
if ! ui_confirm "Финальное подтверждение" "$confirmation_text"; then
|
||||||
|
ui_show_message "Отмена" "Операция отменена пользователем."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. Создаем выходной каталог, если его нет
|
||||||
|
if [ ! -d "$OUTPUT_BASE_DIR" ]; then
|
||||||
|
if ui_confirm "Создание каталога" "Каталог '$OUTPUT_BASE_DIR' не существует. Создать его?"; then
|
||||||
|
mkdir -p "$OUTPUT_BASE_DIR"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
ui_show_message "Ошибка" "Не удалось создать каталог '$OUTPUT_BASE_DIR'."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
ui_show_message "Отмена" "Операция отменена, так как выходной каталог не существует."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 5. Выполнение операции с прогресс-баром
|
||||||
|
local total_files=${#FILE_TRIPLETS[@]}
|
||||||
|
local current_file=0
|
||||||
|
|
||||||
|
(
|
||||||
|
for triplet in "${FILE_TRIPLETS[@]}"; do
|
||||||
|
# Рассчитываем прогресс
|
||||||
|
local progress=$(( 100 * current_file / total_files ))
|
||||||
|
echo "$progress"
|
||||||
|
|
||||||
|
# Обновляем текст в прогресс-баре
|
||||||
|
echo -e "XXX\n$((current_file + 1)) / $total_files\nОбработка: $(basename "$triplet" | cut -f1 -d$'\t')\nXXX"
|
||||||
|
|
||||||
|
# Разбираем триплет
|
||||||
|
IFS=$'\t' read -r video audio output <<< "$triplet"
|
||||||
|
|
||||||
|
# Выполняем выбранное действие
|
||||||
|
case "$action_to_perform" in
|
||||||
|
"MERGE")
|
||||||
|
action_merge_mkv "$video" "$audio" "$output"
|
||||||
|
;;
|
||||||
|
"SYMLINK")
|
||||||
|
action_create_symlink "$video" "$output"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
((current_file++))
|
||||||
|
done
|
||||||
|
# Для завершения прогресс-бара
|
||||||
|
echo "100"
|
||||||
|
echo -e "XXX\nГотово!\nНажмите Enter для выхода\nXXX"
|
||||||
|
sleep 2
|
||||||
|
) | dialog $DIALOG_OPTS --title "Выполнение..." --gauge "Подготовка..." 10 70 0
|
||||||
|
|
||||||
|
clear
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#==============================================================================
|
||||||
|
# Модуль основной логики: поиск файлов, сопоставление, генерация имён
|
||||||
|
#==============================================================================
|
||||||
|
|
||||||
|
# Глобальная переменная для хранения подготовленных данных
|
||||||
|
# Формат: "видео_файл\tаудио_файл\tвыходной_файл" для каждой строки
|
||||||
|
declare -a FILE_TRIPLETS
|
||||||
|
|
||||||
|
# Основная функция, которая находит и сопоставляет файлы
|
||||||
|
# Возвращает 0 в случае успеха, 1 в случае ошибки
|
||||||
|
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
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 1. Найти видеофайлы
|
||||||
|
# Использование `find ... -print0` и `mapfile` для безопасной обработки имён с пробелами
|
||||||
|
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
|
||||||
|
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"
|
||||||
|
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 output_path="${OUTPUT_BASE_DIR}/${output_name}"
|
||||||
|
|
||||||
|
# Сохраняем триплет в массив
|
||||||
|
FILE_TRIPLETS+=("$video_file"$'\t'"$audio_file"$'\t'"$output_path")
|
||||||
|
done
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Функция для отображения предпросмотра
|
||||||
|
logic_show_preview() {
|
||||||
|
if ! logic_prepare_file_lists; then
|
||||||
|
# Сообщение об ошибке уже было показано внутри logic_prepare_file_lists
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${#FILE_TRIPLETS[@]} -eq 0 ]; then
|
||||||
|
ui_show_message "Предпросмотр" "Нет файлов для обработки."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local preview_text="Будут обработаны следующие файлы (${#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"
|
||||||
|
((count++))
|
||||||
|
done
|
||||||
|
|
||||||
|
ui_show_message "Предпросмотр" "$preview_text"
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#==============================================================================
|
||||||
|
# Модуль интерфейса (TUI) на основе 'dialog'
|
||||||
|
#==============================================================================
|
||||||
|
|
||||||
|
DIALOG_OPTS="--colors --backtitle 'Универсальный обработчик медиа'"
|
||||||
|
|
||||||
|
# Показать главное меню
|
||||||
|
# Принимает массив пунктов меню
|
||||||
|
ui_main_menu() {
|
||||||
|
dialog $DIALOG_OPTS --title "Главное меню" \
|
||||||
|
--menu "Выберите опцию для редактирования или действия:" 20 85 15 "${@}" 2>&1 >/dev/tty
|
||||||
|
}
|
||||||
|
|
||||||
|
# Получить путь к каталогу
|
||||||
|
# $1: Заголовок окна
|
||||||
|
# $2: Текущее значение (для старта)
|
||||||
|
# $3: Путь по умолчанию (если текущее значение пусто)
|
||||||
|
ui_get_directory() {
|
||||||
|
local title="$1"
|
||||||
|
local current_path="$2"
|
||||||
|
local default_path="$3"
|
||||||
|
local start_path="${current_path:-$default_path}"
|
||||||
|
|
||||||
|
# Убедимся, что путь заканчивается на / для dselect
|
||||||
|
[[ "$start_path" != */ ]] && start_path="$start_path/"
|
||||||
|
|
||||||
|
dialog $DIALOG_OPTS --title "$title" \
|
||||||
|
--dselect "$start_path" 10 70 2>&1 >/dev/tty
|
||||||
|
}
|
||||||
|
|
||||||
|
# Получить текстовый ввод от пользователя
|
||||||
|
# $1: Заголовок окна
|
||||||
|
# $2: Текущее значение
|
||||||
|
ui_get_input() {
|
||||||
|
local title="$1"
|
||||||
|
local current_value="$2"
|
||||||
|
|
||||||
|
dialog $DIALOG_OPTS --title "$title" \
|
||||||
|
--inputbox "Введите новое значение:" 10 70 "$current_value" 2>&1 >/dev/tty
|
||||||
|
}
|
||||||
|
|
||||||
|
# Показать информационное сообщение
|
||||||
|
# $1: Заголовок
|
||||||
|
# $2: Текст сообщения
|
||||||
|
ui_show_message() {
|
||||||
|
local title="$1"
|
||||||
|
local text="$2"
|
||||||
|
dialog $DIALOG_OPTS --title "$title" --msgbox "$text" 20 70
|
||||||
|
}
|
||||||
|
|
||||||
|
# Показать окно с выбором Да/Нет
|
||||||
|
# $1: Заголовок
|
||||||
|
# $2: Текст вопроса
|
||||||
|
ui_confirm() {
|
||||||
|
local title="$1"
|
||||||
|
local text="$2"
|
||||||
|
dialog $DIALOG_OPTS --title "$title" --yesno "$text" 10 70
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
# Показать меню выбора действия перед запуском
|
||||||
|
ui_select_action() {
|
||||||
|
dialog $DIALOG_OPTS --title "Выбор действия" \
|
||||||
|
--menu "Какую операцию выполнить с найденными файлами?" 15 70 2 \
|
||||||
|
"MERGE" "Склеить видео и аудио с помощью mkvmerge" \
|
||||||
|
"SYMLINK" "Создать символические ссылки на видеофайлы" 2>&1 >/dev/tty
|
||||||
|
}
|
||||||
Executable
+102
@@ -0,0 +1,102 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#==============================================================================
|
||||||
|
# Универсальный скрипт для обработки медиафайлов с TUI-интерфейсом
|
||||||
|
#==============================================================================
|
||||||
|
|
||||||
|
# --- Подключение модулей ---
|
||||||
|
# Убедимся, что скрипты-модули находятся в том же каталоге
|
||||||
|
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)
|
||||||
|
source "$SCRIPT_DIR/core_ui.sh"
|
||||||
|
source "$SCRIPT_DIR/core_logic.sh"
|
||||||
|
source "$SCRIPT_DIR/core_actions.sh"
|
||||||
|
|
||||||
|
# --- Конфигурация по умолчанию (можно менять) ---
|
||||||
|
# Эти пути будут предлагаться по умолчанию в диалогах выбора
|
||||||
|
DEFAULT_ROOT_PATH="/var/www/nextcloud/data/grayhook/files/"
|
||||||
|
DEFAULT_TORRENTS_DIR="${DEFAULT_ROOT_PATH}/Torrents"
|
||||||
|
DEFAULT_ARCHIVE_DIR="${DEFAULT_ROOT_PATH}/Archive/Anime"
|
||||||
|
|
||||||
|
# --- Переменные состояния (будут меняться через интерфейс) ---
|
||||||
|
VIDEO_SRC_DIR=""
|
||||||
|
AUDIO_SRC_DIR=""
|
||||||
|
OUTPUT_BASE_DIR=""
|
||||||
|
OUTPUT_SERIES_NAME=""
|
||||||
|
SEASON_NUMBER="01"
|
||||||
|
|
||||||
|
# Паттерны для поиска файлов (можно использовать find-совместимые wildcards)
|
||||||
|
VIDEO_FILE_PATTERN="*.mkv"
|
||||||
|
AUDIO_FILE_PATTERN="*.mka"
|
||||||
|
|
||||||
|
# Регулярное выражение для извлечения номера серии из ИМЕНИ ВИДЕОФАЙЛА
|
||||||
|
# Использует синтаксис ERE (sed -E). Группа захвата (в скобках) должна поймать номер.
|
||||||
|
EPISODE_NUMBER_REGEX='.* ([0-9]{2}) .*'
|
||||||
|
|
||||||
|
# Шаблон для имени выходного файла. Заполнители будут заменены.
|
||||||
|
# {SERIES_NAME} - Имя сериала
|
||||||
|
# {SEASON} - Номер сезона (с ведущим нулём)
|
||||||
|
# {EPISODE} - Номер эпизода (с ведущим нулём, извлечённый regex'ом)
|
||||||
|
OUTPUT_FILENAME_TEMPLATE="{SERIES_NAME} s{SEASON}e{EPISODE}.mkv"
|
||||||
|
|
||||||
|
# --- Главный цикл программы ---
|
||||||
|
main() {
|
||||||
|
while true; do
|
||||||
|
# Формируем пункты меню с текущими значениями
|
||||||
|
menu_items=(
|
||||||
|
"V" "Видео каталог : ${VIDEO_SRC_DIR:-_не задан_}"
|
||||||
|
"A" "Аудио каталог : ${AUDIO_SRC_DIR:-_не задан_}"
|
||||||
|
"O" "Выходной каталог : ${OUTPUT_BASE_DIR:-_не задан_}"
|
||||||
|
"N" "Имя для Plex : ${OUTPUT_SERIES_NAME:-_не задано_}"
|
||||||
|
"S" "Номер сезона : $SEASON_NUMBER"
|
||||||
|
"" "--- Шаблоны и Regex ---"
|
||||||
|
"P" "Шаблон видеофайлов : $VIDEO_FILE_PATTERN"
|
||||||
|
"U" "Шаблон аудиофайлов : $AUDIO_FILE_PATTERN"
|
||||||
|
"R" "Regex номера серии : $EPISODE_NUMBER_REGEX"
|
||||||
|
"T" "Шаблон имени вывода : $OUTPUT_FILENAME_TEMPLATE"
|
||||||
|
"" "--- Действия ---"
|
||||||
|
"VIEW" "Предпросмотр сопоставления файлов"
|
||||||
|
"RUN" "ЗАПУСТИТЬ обработку"
|
||||||
|
)
|
||||||
|
|
||||||
|
choice=$(ui_main_menu "${menu_items[@]}")
|
||||||
|
|
||||||
|
# Выход из скрипта по кнопке Cancel или Esc
|
||||||
|
if [[ -z "$choice" ]]; then
|
||||||
|
clear
|
||||||
|
echo "Выход."
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$choice" in
|
||||||
|
V) VIDEO_SRC_DIR=$(ui_get_directory "Выберите каталог с видеофайлами" "$VIDEO_SRC_DIR" "$DEFAULT_TORRENTS_DIR") ;;
|
||||||
|
A) AUDIO_SRC_DIR=$(ui_get_directory "Выберите каталог с аудиофайлами" "$AUDIO_SRC_DIR" "$VIDEO_SRC_DIR") ;;
|
||||||
|
O) OUTPUT_BASE_DIR=$(ui_get_directory "Выберите БАЗОВЫЙ каталог для результата" "$OUTPUT_BASE_DIR" "$DEFAULT_ARCHIVE_DIR") ;;
|
||||||
|
N) OUTPUT_SERIES_NAME=$(ui_get_input "Введите имя сериала для Plex" "$OUTPUT_SERIES_NAME") ;;
|
||||||
|
S) SEASON_NUMBER=$(ui_get_input "Введите номер сезона (например, 01, 02)" "$SEASON_NUMBER") ;;
|
||||||
|
P) VIDEO_FILE_PATTERN=$(ui_get_input "Введите шаблон для поиска видео (*.mkv, *ep*.mkv)" "$VIDEO_FILE_PATTERN") ;;
|
||||||
|
U) AUDIO_FILE_PATTERN=$(ui_get_input "Введите шаблон для поиска аудио (*.mka, *.ac3)" "$AUDIO_FILE_PATTERN") ;;
|
||||||
|
R) EPISODE_NUMBER_REGEX=$(ui_get_input "Введите ERE-regex для номера серии" "$EPISODE_NUMBER_REGEX") ;;
|
||||||
|
T) OUTPUT_FILENAME_TEMPLATE=$(ui_get_input "Введите шаблон имени выходного файла" "$OUTPUT_FILENAME_TEMPLATE") ;;
|
||||||
|
|
||||||
|
VIEW)
|
||||||
|
# Вызываем предпросмотр
|
||||||
|
logic_show_preview
|
||||||
|
;;
|
||||||
|
|
||||||
|
RUN)
|
||||||
|
# Вызываем меню выбора действия и запускаем обработку
|
||||||
|
run_processing
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Точка входа ---
|
||||||
|
# Проверка наличия dialog
|
||||||
|
if ! command -v dialog &> /dev/null; then
|
||||||
|
echo "Команда 'dialog' не найдена. Пожалуйста, установите ее."
|
||||||
|
echo "sudo apt-get install dialog (Debian/Ubuntu)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
main
|
||||||
Reference in New Issue
Block a user