Compare commits
5 Commits
29e5e21825
...
8dafbccef1
Author | SHA1 | Date | |
---|---|---|---|
8dafbccef1 | |||
913cc95326 | |||
0fd3bbaad9 | |||
749750fbb7 | |||
bef6ad9438 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
__pycache__/
|
11
Taskfile.yml
Normal file
11
Taskfile.yml
Normal file
@ -0,0 +1,11 @@
|
||||
# https://taskfile.dev
|
||||
|
||||
version: '3'
|
||||
|
||||
vars:
|
||||
GREETING: Hello, World!
|
||||
|
||||
tasks:
|
||||
format:
|
||||
cmds:
|
||||
- docker run --rm --volume $(pwd):/src --workdir /src pyfound/black:25.1.0 black .
|
34
convert_file_encoding.py
Normal file
34
convert_file_encoding.py
Normal file
@ -0,0 +1,34 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def convert_encoding(filepath):
|
||||
try:
|
||||
with open(filepath, "r", encoding="cp1251", errors="strict") as f:
|
||||
content = f.read()
|
||||
|
||||
with open(filepath, "w", encoding="utf-8", errors="strict") as f:
|
||||
f.write(content)
|
||||
|
||||
print(f"Success: {filepath}")
|
||||
|
||||
except UnicodeDecodeError:
|
||||
print(f"Error: {filepath} - not cp1251 encoded")
|
||||
except Exception as e:
|
||||
print(f"Error: {filepath} - {str(e)}")
|
||||
|
||||
|
||||
def process_directory(root_dir):
|
||||
if not os.path.isdir(root_dir):
|
||||
print(f"Error: '{root_dir}' is not a valid directory")
|
||||
sys.exit(1)
|
||||
|
||||
for root, _, files in os.walk(root_dir):
|
||||
for file in files:
|
||||
if file.endswith((".cue", ".log")):
|
||||
file_path = os.path.join(root, file)
|
||||
convert_encoding(file_path)
|
||||
|
||||
|
||||
def execute(args):
|
||||
process_directory(args.directory)
|
@ -1,46 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import convert_file_encoding
|
||||
import split_flac
|
||||
|
||||
def convert_encoding(filepath):
|
||||
try:
|
||||
with open(filepath, 'r', encoding='cp1251', errors='strict') as f:
|
||||
content = f.read()
|
||||
|
||||
with open(filepath, 'w', encoding='utf-8', errors='strict') as f:
|
||||
f.write(content)
|
||||
|
||||
print(f"Success: {filepath}")
|
||||
|
||||
except UnicodeDecodeError:
|
||||
print(f"Error: {filepath} - not cp1251 encoded")
|
||||
except Exception as e:
|
||||
print(f"Error: {filepath} - {str(e)}")
|
||||
|
||||
def process_directory(root_dir):
|
||||
for root, _, files in os.walk(root_dir):
|
||||
for file in files:
|
||||
if file.endswith(('.cue', '.log')):
|
||||
file_path = os.path.join(root, file)
|
||||
convert_encoding(file_path)
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Recursively convert .cue and .log files from cp1251 to utf-8',
|
||||
epilog='Example: python convert_encoding.py /path/to/directory'
|
||||
def create_convert_parser(subparsers):
|
||||
parser = subparsers.add_parser(
|
||||
"convert",
|
||||
description="Recursively convert .cue and .log files from cp1251 to utf-8",
|
||||
epilog="Example: python convert_encoding.py /path/to/directory",
|
||||
)
|
||||
parser.add_argument(
|
||||
'directory',
|
||||
type=str,
|
||||
help='Path to target directory for conversion'
|
||||
"directory", type=str, help="Path to target directory for conversion"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not os.path.isdir(args.directory):
|
||||
print(f"Error: '{args.directory}' is not a valid directory")
|
||||
sys.exit(1)
|
||||
|
||||
process_directory(args.directory)
|
||||
parser.set_defaults(func=convert_file_encoding.execute)
|
||||
|
||||
|
||||
def create_split_parser(subparsers):
|
||||
parser = subparsers.add_parser(
|
||||
"split",
|
||||
description="Разделение FLAC-файла по CUE с переносом оригинала во временную директорию",
|
||||
)
|
||||
parser.add_argument(
|
||||
"directory", type=str, help="Path to target directory with flac and cue files"
|
||||
)
|
||||
parser.set_defaults(func=split_flac.execute)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
top_parser = argparse.ArgumentParser()
|
||||
subparsers = top_parser.add_subparsers()
|
||||
create_convert_parser(subparsers)
|
||||
create_split_parser(subparsers)
|
||||
|
||||
args = top_parser.parse_args()
|
||||
print(args)
|
||||
args.func(args)
|
||||
|
109
split_flac.py
Normal file
109
split_flac.py
Normal file
@ -0,0 +1,109 @@
|
||||
import argparse
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import sys
|
||||
|
||||
|
||||
def ensure_utils():
|
||||
if not all(shutil.which(cmd) for cmd in ["shnsplit", "cuetag"]):
|
||||
raise RuntimeError("Ошибка: Требуются shnsplit и cuetag")
|
||||
|
||||
|
||||
def find_cue_file(directory):
|
||||
cue_files = []
|
||||
for f in os.listdir(directory):
|
||||
if f.lower().endswith(".cue"):
|
||||
cue_files.append(f)
|
||||
if len(cue_files) != 1:
|
||||
for f in cue_files:
|
||||
print("Found CUE-file", f)
|
||||
raise RuntimeError("Error: found multiple cue files")
|
||||
return cue_files[0]
|
||||
|
||||
|
||||
def find_flac_file(directory, cue_file):
|
||||
cue_basename, _ = os.path.splitext(cue_file)
|
||||
flac_file = cue_basename + ".flac"
|
||||
if not os.path.exists(os.path.join(directory, flac_file)):
|
||||
raise RuntimeError("Error: flac file not found", flac_file)
|
||||
return flac_file
|
||||
|
||||
|
||||
def process_directory(directory):
|
||||
print("Search files in", directory)
|
||||
|
||||
cue_file = find_cue_file(directory)
|
||||
print("CUE:", cue_file)
|
||||
|
||||
flac_file = find_flac_file(directory, cue_file)
|
||||
print("FLAC:", flac_file)
|
||||
|
||||
flac_full_path = os.path.join(directory, flac_file)
|
||||
|
||||
# Создание временной директории
|
||||
with tempfile.TemporaryDirectory(dir=directory) as tmp_dir:
|
||||
try:
|
||||
# Перенос оригинального FLAC во временную директорию
|
||||
print("Move original FLAC file to", tmp_dir)
|
||||
tmp_flac = os.path.join(tmp_dir, flac_file)
|
||||
shutil.move(flac_full_path, tmp_flac)
|
||||
|
||||
# Выполнение разделения в исходной директории
|
||||
print("Split FLAC-file...")
|
||||
subprocess.run(
|
||||
[
|
||||
"shnsplit",
|
||||
"-f",
|
||||
cue_file,
|
||||
"-o",
|
||||
"flac",
|
||||
"-t",
|
||||
"%n - %t",
|
||||
tmp_flac,
|
||||
],
|
||||
cwd=directory,
|
||||
check=True,
|
||||
)
|
||||
|
||||
# Добавление метаданных
|
||||
print("Add tags from CUE-file...")
|
||||
split_files = [f for f in os.listdir(directory) if f.endswith(".flac")]
|
||||
|
||||
if split_files:
|
||||
subprocess.run(
|
||||
["cuetag", cue_file] + split_files,
|
||||
cwd=directory,
|
||||
check=True,
|
||||
)
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error: {e}")
|
||||
# Возврат оригинала при ошибке
|
||||
shutil.move(tmp_flac, flac_full_path)
|
||||
return
|
||||
|
||||
print("Done! File split and tagged")
|
||||
|
||||
|
||||
def find_all_directories(root_dir):
|
||||
"""Рекурсивный поиск всех поддиректорий в указанной директории"""
|
||||
dir_list = []
|
||||
for root, dirs, _ in os.walk(root_dir):
|
||||
for dir_name in dirs:
|
||||
if not dir_name.startswith("."):
|
||||
full_path = os.path.join(root, dir_name)
|
||||
dir_list.append(full_path)
|
||||
return dir_list
|
||||
|
||||
|
||||
def execute(args):
|
||||
root_dir = args.directory
|
||||
for d in find_all_directories(root_dir):
|
||||
try:
|
||||
process_directory(d)
|
||||
except:
|
||||
print("Failed", d)
|
||||
print("Continue")
|
||||
print()
|
Loading…
Reference in New Issue
Block a user