Created
June 3, 2020 19:53
-
-
Save rlaphoenix/bc97d596130a7970e0e5d89454c6f0ec to your computer and use it in GitHub Desktop.
Pack rar files into neat split volumes based on max volume size and max volume count.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# std | |
import os | |
import glob | |
import math | |
import subprocess | |
import binascii | |
import argparse | |
# Arguments | |
ArgParser = argparse.ArgumentParser() | |
ArgParser.add_argument("-i", "--input", | |
type=str, required=True, | |
help="Input file to be packed. If a directory is provided, each file in it will be packed seperately.") | |
ArgParser.add_argument("-s", "--size", | |
type=int, default=50000000, required=False, | |
help="Maximum size (in bytes) of each rar volume.") | |
ArgParser.add_argument("-m", "--max", | |
type=int, default=101, required=False, | |
help="Maxmimum splits, will incrememnt the size and re-calculate until its less than or equal to this number.") | |
args = ArgParser.parse_args() | |
# Create Packer Class | |
class Packer(): | |
def __init__(self, file_paths): | |
for file_path in file_paths: | |
# pack and split the file with rar | |
split_count = self.split_file(file_path) | |
# get an extensionless and lower-case named path | |
base_path = os.path.join( | |
os.path.dirname(file_path), | |
os.path.splitext(os.path.basename(file_path))[0].lower() | |
) | |
# generate an sfv using the base_path and split_count data | |
self.generate_sfv( | |
file_paths=[ | |
base_path + (".rar" if x == 0 else f".r{str(x - 1).zfill(2)}") for x in range(split_count) | |
], | |
save_path=f"{base_path}.sfv" | |
) | |
def split_file(self, file_path): | |
"""split file and return split count""" | |
# get initial split size | |
split_size = args.size | |
# get the file size of the input as bytes | |
file_size = os.path.getsize(file_path) | |
print(f"File Size: {file_size}") | |
# calculate split count for the initial SPLIT_SIZE | |
split_count = math.ceil(file_size / split_size) | |
while split_count > args.max: | |
split_size += args.size | |
print(f"Incrememnted split size as the calculated split count is greater than args.max: {split_size}") | |
split_count = math.ceil(file_size / split_size) | |
print(f"Split Count: {split_count}") | |
# use rar to archive it and split it | |
subprocess.run([ | |
"rar", | |
"a", | |
"-m0", "-ma4", "-vn", f"-v{split_size}b", "-ep1", | |
f"{os.path.splitext(os.path.basename(file_path))[0].lower()}.rar", file_path | |
], cwd=os.path.dirname(file_path)) | |
return split_count | |
def generate_sfv(self, file_paths, save_path): | |
"""generate sfv checksum file""" | |
with open(save_path, "wt") as SFV: | |
for file_path in file_paths: | |
with open(file_path, "rb") as f: | |
buf = f.read() | |
buf = (binascii.crc32(buf) & 0xFFFFFFFF) | |
buf = "%08X" % buf | |
SFV.write(f"{os.path.basename(file_path)} {buf}\n") | |
print(f"Generated CRC32 for {os.path.basename(file_path)}: {buf}") | |
# Compile path list and send it to the packer | |
file_paths = [] | |
if os.path.isfile(args.input): | |
file_paths.append(args.input) | |
else: | |
file_paths += glob.glob(os.path.join(args.input, "*")) | |
packer = Packer(file_paths) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment