Crie muitos arquivos tar a partir de um diretório com 500000 arquivos

2

Eu tenho um diretório contendo cerca de 500k arquivos e quero dividi-los em arquivos t tar.

Coloque formalmente, vamos chamar os arquivos file_0, ..., file_{N-1} , onde N em torno de 500k. Eu quero criar arquivos t tar contendo cada% arquivos T=N/t , onde o arquivo i-th tar contém

file_(i*N), ..., file_((i+1)*N - 1),    i in {0, ..., t-1}

Qual é uma maneira eficiente de fazer isso? Eu estava indo para escrever um script Python que apenas faz um loop sobre os arquivos N e os divide em t pastas, e então chama tar em cada, mas isso é muito pouco ideal. Eu tenho muitos núcleos no servidor e sinto que isso deve acontecer em paralelo.

    
por fabian789 09.05.2017 / 16:16

2 respostas

4

Você pode usar a biblioteca python concurrent , que é projetada para processar uma fila de solicitações entre todos ou alguns segmentos, comendo a fila até que todos os trabalhos sejam executados inteiramente.

  1. Gerar uma lista grande de arquivos, como [ [f0..f0-1], [fn..f2n-1]..]
  2. Use um ThreadPoolExecutor para comer essa lista com todos muitos thread seu computador tem. Isso pode ser assim:
import os
import sys
from concurrent.futures import ThreadPoolExecutor
import subprocess
import itertools
import math


def main(p, num_tar_files):
    files = list(split_files_in(p, num_tar_files))
    tar_up = tar_up_fn(p)
    with ThreadPoolExecutor(len(files)) as executor:
        archives = list(executor.map(tar_up, itertools.count(), files))
        print("\n {} archives generated".format(len(archives)))


def split_files_in(p, num_slices):
    files = sorted(os.listdir(p))
    N = len(files)
    T = int(math.ceil(N / num_slices))  # means last .tar might contain <T files
    for i in range(0, N, T):
        yield files[i:i+T]


def tar_up_fn(p):
    def tar_up(i, files):
        _, dir_name = os.path.split(p)
        tar_file_name = "{}_{:05d}.tar".format(dir_name, i)
        print('Tarring {}'.format(tar_file_name))
        subprocess.call(["tar", "-cf", tar_file_name] + files, cwd=p)
        return tar_file_name
    return tar_up


if __name__ == '__main__':
    main(sys.argv[1], int(sys.argv[2]))
    
por 09.05.2017 / 21:32
0

usando zsh para criar listas para tar

Espero ter entendido o que você está tentando fazer. t=731 foi apenas um número que eu escolhi no ar. Hack, conforme necessário. O seguinte cria vários arquivos com nomes de arquivos t ou o último arquivo com os nomes de arquivos restantes, se não forem iguais a t .

Var=(*(.)) # glob files in current directory
VarSorted=(${(on)Var})  # numeric sort
fn=1  # Tar list file number
t=731  # Number of files in each tar file
for (( i = 1 ; i <= ${#VarSorted} ; i = i + t ))
do
  print -l -- ${VarSorted[$i,$i+$t-1]} > /tmp/tar_file_list_${(l:5::0:)fn}
  (( fn++ ))
done

Use a opção tar ou -t (short / long form) do comando --files-from para gerar cada arquivo tar. Isso também pode ser roteirizado.

    
por 20.06.2017 / 00:20