Алгоритм видится мне следущий:
0. Исходим из предположения, что размер архива данной папки не превосходит ее исходного размера (т.е. архивация не увеличивает занимаемого объема)
1. Создаем массив кортежей т.е. пути к файлам и размеры файлов соответственно (это можно сделать при помощи os модуля)
2. сортируем данный массив по размеру файлов, допустим по возрастанию (как-нибудь так: x=sorted(x, key=lambda x: x))
3. дальше создаем цикл типа while пока текущий массив кортежей непуст, а внутри него другой цикл, который последовательно от большего к меньшему пробует добавить каждый файл, пока размер контейнера меньше 50 МБ:
files_array= [('path/to/file', file_size), ....] # sort it first...
containers = []
while files_array:
container = []
pendings = []
for k in reversed(range(len(files_array))):
container.append(files_array[k])
pendings.append(k)
if sum(map(lambda x: x[1], container)) >= 50:
container.pop()
pendings.pop()
containers.append(container)
for i in pendings:
del files_array[i] # удаляем тех, кто в списке не удаление
В результате, получим оптимальный массив контейнеров – каждый из которых не превосходит 50 МБ. Далее, в соответствии с файлами в контейнерах, можно сформировать директории и их упаковать.