Interesting problem! I don't know any software to achieve what you want, but how about something like this?
#!/usr/bin/env python
import os, operator, sys
limit = int(sys.argv[1])
dirpath = os.path.abspath(sys.argv[2])
# make a generator for all file paths within dirpath
all_files = ( (os.path.join(basedir, filename) for basedir, dirs, files in os.walk(dirpath) for filename in files))
all_file_sizes = ((os.path.getsize(fname), fname) for fname in all_files)
sorted_files = sorted(all_file_sizes)
def yield_groups(size_filenames, limit):
cumulative_size = 0
file_list = []
for file_size, file_name in size_filenames:
new_size = cumulative_size + file_size
#print "%r" % new_size, "%r" %limit, new_size > limit, file_name
if new_size > limit:
#print "bigger"
yield file_list
file_list = [file_name]
cumulative_size = file_size
else:
file_list.append(file_name)
cumulative_size += file_size
yield file_list
for i, group in enumerate(yield_groups(sorted_files, limit)):
print ("tar -cvf /tmp/group-%03u.tar %s" % (i, ' '.join(group)))
It seems to work reasonably well for me:
➜ chunks>du -hs *
1,0M file1
1,0M file2
1,0M file3
1,0M file4
1,0M file5
2,0M file6
2,0M file7
3,0M file8
3,0M file9
Now requesting groups of 3MB:
➜ chunks>python /tmp/sizezip.py 3145728 /tmp//chunks/
tar -cvf /tmp/group-000.tar /tmp/chunks/file1 /tmp/chunks/file2 /tmp/chunks/file3
tar -cvf /tmp/group-001.tar /tmp/chunks/file4 /tmp/chunks/file5
tar -cvf /tmp/group-002.tar /tmp/chunks/file6
tar -cvf /tmp/group-003.tar /tmp/chunks/file7
tar -cvf /tmp/group-004.tar /tmp/chunks/file8
tar -cvf /tmp/group-005.tar /tmp/chunks/file9
Or rather 5MB:
➜ chunks>python /tmp/sizezip.py 5242880 /tmp//chunks/
tar -cvf /tmp/group-000.tar /tmp/chunks/file1 /tmp/chunks/file2 /tmp/chunks/file3 /tmp/chunks/file4 /tmp/chunks/file5
tar -cvf /tmp/group-001.tar /tmp/chunks/file6 /tmp/chunks/file7
tar -cvf /tmp/group-002.tar /tmp/chunks/file8
tar -cvf /tmp/group-003.tar /tmp/chunks/file9
Note that this is quick and dirty code. It does not even attempt to solve the Knapsack problem.