Dividir um grupo de arquivos em vários CDs Ou DVDs
Publicado por Marcelo Barros de Almeida 29/09/2005
[ Hits: 7.186 ]
Este script permite que uma série de arquivos sejam organizados em vários DVDs/CDs de forma otimizada, isto é, tentando sempre utilizar ao máximo o espaço disponível na mídia. É útil quando você não quer pensar muito na melhor organização e eu venho usado para organizar os meus arquivos de backup. Ao final, ele lista uma opção de organização. Como o algoritmo é estatístico, você pode rodar novamente para ter um resultado diferente, apesar de construído com os mesmos critérios.
"""
Este programa usa uma rede neural do tipo Hopfield para a solução do problema. Basicamente é necessário especificar o diretório onde os arquivos estão, o tamanho da mídia e a folga máxima. Se nenhum parâmetro é especificado, é usado o diretório corrente, uma mídia de 4500MB (DVD) e uma folga de 50MB. A folga diz o quanto o algoritmo pode encarar margem de erro, já que em geral não é possível ter uma divisão sempre perfeita.
Rode com dvdsplit.py -h para informações da linha de comando. É meu primeiro programa em Python, comentário são bem vindos.
"""
"""
DVD Split, by Marcelo Barros (marcelobarrosalmeida(at)yahoo.com.br)
Sept/13/2005
$Id: dvdsplit.py,v 1.1 2005/09/13 14:54:36 barros Exp $
"""
import random
import math
import os
import sys
from optparse import OptionParser
import psyco
def currentSize(files, selected):
"""
Calculate the size of the current selection.
Parameters:
- files: list with file sizes
- selected: list with 1 or -1, indicating if the file was selected or not
Returns:
- the current selection size
"""
sz = 0
for i in range(len(files)):
if(selected[i] > 0):
sz = sz + files[i]
return sz
def energyFun(files,selected,dvdsz):
"""
Energy function used. In this case is:
f(x) = |current_size - dvdsize |
Parameters:
- files: list with file sizes
- selected: list with 1 or -1, indicating if the file was selected or not
- dvdsz: dvd size
Returns:
- energy function value for the current selection
"""
energ = 0
for i in range(len(files)):
if selected[i] > 0:
energ = energ + files[i]
energ = abs(energ - dvdsz)
return energ
def dvdInitialGuess(files,selected,dvdsz):
"""
Just provide an initial random guess to the algorithm
Parameters:
- files: list with file sizes
- selected: list with 1 or -1, indicating if the file was selected or not
- dvdsz: dvd size
"""
l = len(files)
idx = range(l)
idx = random.sample(idx,l)
t = 0
for i in range(l):
j = idx[i]
t = t + files[j]
selected[j] = 1
if t >= dvdsz:
break
def dvdSplit(files,dvdsz,slack=50,itermax=3000,beta=0.005):
"""
Given a list with file sizes, the dvd size and the acceptable slack
this routine gives a subset that fits in one dvd.
Parameters:
- files: list with file sizes
- dvdsz: dvd size (single side)
- slack: maximum acceptable error when calculating the selection
- itermax: maximum number of iteration (default=2000)
- beta: sigmoid parameter (default 0.005, empirically determined)
Returns:
- indexes of selected files: [ idx1, idx2, ..., idxn ]
- indexes of not selected files: [ idx1, idx2, ..., idxn ]
- current selection size
- iteration used to calculate
"""
running = True
iter = 0
numfiles = len(files)
selected = [-1 for x in range(numfiles)]
dvdInitialGuess(files,selected,dvdsz)
sz = currentSize(files,selected) # maximum size must be greather than dvdsize
if(sz > dvdsz):
while(running and iter < itermax):
# current energy
e1 = energyFun(files,selected,dvdsz)
# change state for random node
n = random.randint(0,numfiles-1)
selected[n] = -selected[n]
# new energy
e2 = energyFun(files,selected,dvdsz)
# evaluate the change against sigmoid and accept it or not
# according to a uniform probability
sig = (1/( 1 + math.exp(beta*(e2-e1))))
if sig < random.uniform(0,1):
selected[n] = -selected[n] # state not accepted
sz = currentSize(files,selected)
# testing exit condition: (dvdsz - slack) < currentSize < dvdsz
if ( (sz >= (dvdsz - slack)) and (sz < dvdsz) ):
running = False
iter = iter + 1
sel = []
notsel = []
for i in range(numfiles):
if selected[i] > 0:
sel.append(i)
else:
notsel.append(i)
#print "Solution found in %d iterations. Compilation size is %d (%d files)" % (iter,sz,len(sel))
return sel,notsel,sz,iter
def dvdsSplit(files,dvdsz,slack=50,itermax=3000,beta=0.005):
"""
Given a list with file sizes, the dvd size and the acceptable slack
this routine distributes the selection over several dvs.
Parameters:
- files: list with file sizes
- dvdsz: dvd size (single side)
- slack: maximum acceptable error when calculating the selection (default=50)
- itermax: maximum number of iteration (default=2000)
- beta: sigmoid parameter (default 0.005, empirically determined)
Returns:
- indexes of selected files per dvds:
[ [idx1, idx2, ..., idxn], [idx1, idx2, ..., idxm], ..., [idx1, idx2, ..., idxk] ]
- compilation sizes: [ size1, size2, ..., sizen ]
"""
# first create a dictionary with all file sizes indexed. Files choosen
# by dvdSplit will be removed from this dictionary until it becomes empty
filesdic = dict()
n = len(files)
for i in range(n):
filesdic[i] = files[i]
dvds = []
sz = []
running = True
r = 1
while(running):
v = filesdic.values()
k = filesdic.keys()
print "Starting DVD %02d [%3.2f%% completed]" % (r,100-100*len(v)/n)
maxtries = 50
while(True):
sel,ns,dsz,iter = dvdSplit(v,dvdsz,slack,itermax,beta)
if dsz < dvdsz:
break;
maxtries = maxtries - 1
if(maxtries == 0):
print "Could not find a good solution for DVD %d in 50 attempts. Try again, please." % (r)
sys.exit(1)
# getting indexes
r = r + 1
d = []
for s in sel:
d.append(k[s])
del filesdic[k[s]]
# saving dvd compilation
dvds.append(d)
sz.append(dsz)
if len(ns) == 0:
running = False
return dvds, sz
def dvdConsistency(filenames,filesizes,dvdsz):
"""
Consistency checks.
Parameters:
- filenames: file names dict
- filesizes: file sizes dict
- dvds: dvd size
"""
# look for any file bigger than dvd side
for i in filesizes:
if filesizes[i] >= dvdsz:
print "Size %d is bigger than dvd size %d" % (filesizes[i],dvdsz)
sys.exit(1)
def printDvdLayout(filesizes,filenames,dvdsz,dvds,s):
"""
Print results
"""
i = 0
n = len(dvds)
tts = []
print "\nSummary:"
for dvd in dvds:
tt = []
i = i + 1
for track in dvd:
tt.append(filesizes[track])
tts.append(sum(tt))
print "[DVD %d/%d, SIZE %dMBs, USAGE %2.2f%%]" % (i,n,tts[i-1],100.0*tts[i-1]/dvdsz)
i = 0
print "\nFile seletion per DVD:"
for dvd in dvds:
i = i + 1
print "[DVD %d/%d, SIZE %dMBs]" % (i,n,tts[i-1])
for track in dvd:
files = filenames[track].split(',')
files.sort()
for f in files:
print "\t%s" % (f)
def buildDvds(basedir,dvdsz,slack):
"""
Get the files list and call optimization routines
"""
filelist = os.listdir(basedir)
filenames = dict()
filesizes = dict()
i = 0
print "\nFiles at base directory %s (DVD size = %d, slack = %d)" % (basedir,dvdsz,slack)
for f in filelist:
filename = basedir+f
if os.path.isfile(filename):
filenames[i] = f
# in MB, rounded up
filesizes[i] = int(os.path.getsize(filename)/1024.0**2 + 1)
print '[%5.2fMB ] %s' % (filesizes[i],filenames[i])
i = i + 1
print "\nChecking consistency ..."
dvdConsistency(filenames,filesizes,dvdsz)
dvds, s = dvdsSplit(filesizes.values(),dvdsz,slack)
printDvdLayout(filesizes,filenames,dvdsz,dvds,s)
def main():
usage = "Usage: %prog [options]"
cmdline = OptionParser(usage)
cmdline.add_option("-d", "--dir", action="store", dest="basedir", type="string", default=".", metavar="DIR", help="Directory where files are stored")
cmdline.add_option("-s", "--size", action="store", dest="dvdsz", type="int", default="4500", metavar="SIZE", help="DVD size")
cmdline.add_option("-l", "--slack",action="store", dest="slack", type="int", default="50", metavar="SLACK", help="Maximum acceptable error")
(options, args) = cmdline.parse_args()
if(os.path.isdir(options.basedir) == False):
print "%s is not a valid directory" %(options.basedir)
sys.exit(1)
options.basedir.strip()
basedir = os.path.normpath(options.basedir)
if(os.path.isdir("c:\\")):
basedir = basedir + "\\"
else:
basedir = basedir + "//"
buildDvdsPrx = psyco.proxy(buildDvds)
buildDvdsPrx(basedir,int(options.dvdsz),int(options.slack))
if __name__ == "__main__":
main()
Manipulando arquivos com Pickle
Detectando e excluindo imagens em branco obtidas de scanner
ShellCrypTor criptografador de dados
Nenhum comentário foi encontrado.
IA Turbina o Desktop Linux enquanto distros renovam forças
Como extrair chaves TOTP 2FA a partir de QRCODE (Google Authenticator)
Linux em 2025: Segurança prática para o usuário
Desktop Linux em alta: novos apps, distros e privacidade marcam o sábado
IA chega ao desktop e impulsiona produtividade no mundo Linux
Atualizando o Fedora 42 para 43
Como saber se o seu e-mail já teve a senha vazada?
Como descobrir se a sua senha já foi vazada na internet?
Programa fora de escala na tela do pc (40)
\Boot sem espaço em disco (Fedora KDE Plasma 42) (5)
Preciso recuperar videos *.mp4 corrompidos (0)









