Dividir um grupo de arquivos em vários CDs Ou DVDs
Publicado por Marcelo Barros de Almeida 29/09/2005
[ Hits: 6.960 ]
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()
Web Scraping para coletar dados dos pilotos da Fórmula 1
Criando um rootfs para sistemas embarcados a partir de cópia de um sistema já operando
Manipulando as informações do USBfs no Linux
Nenhum comentário foi encontrado.
Enviar mensagem ao usuário trabalhando com as opções do php.ini
Meu Fork do Plugin de Integração do CVS para o KDevelop
Compartilhando a tela do Computador no Celular via Deskreen
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
Compartilhamento de Rede com samba em modo Público/Anônimo de forma simples, rápido e fácil
Cups: Mapear/listar todas as impressoras de outro Servidor CUPS de forma rápida e fácil
Criando uma VPC na AWS via CLI
Impressora Bematech MP4200TH rorando com a distribuição Zorin OS (1)
Testando links de internet (1)
Quando fui olhar as logs achei um erro !!! (1)
Servidor said: 530 5.7.0 Must issue a STARTTLS command first (in r... (5)