Erstellen Sie viele tar-Dateien aus einem Verzeichnis mit 500000 Dateien

453
fabian789

Ich habe ein Verzeichnis mit etwa 500.000 Dateien und möchte sie in ttar-Dateien aufteilen .

Formell ausgedrückt, nennen wir die Dateien file_0, ..., file_, bei denen N500k liegen. Ich möchte ttar-Dateien erstellen, die jeweils Dateien enthalten T=N/t, in denen die i-te tar-Datei enthalten ist

file_(i*N), ..., file_((i+1)*N - 1), i in 

Was ist ein effizienter Weg, dies zu tun? Ich wollte ein Python-Skript schreiben, das nur die NDateien durchläuft und sie in tOrdner taraufteilt und dann in jedem Ordner aufruft, aber das fühlt sich sehr unoptimal an. Ich habe viele Kerne auf dem Server und denke, dass dies parallel passieren sollte.

2
`xjobs` hat die` -l`-Option, um mehrere Eingabeargumente für jeden Job zu kombinieren. Sie müssen jedoch die Dateien separat zählen und vorher durch 'N' teilen. Toby Speight vor 6 Jahren 0

2 Antworten auf die Frage

4
A. Loiseau

Sie können eine Python- concurrentBibliothek verwenden, die eine Anforderungswarteschlange zwischen allen oder einigen Threads verarbeitet und die Warteschlange so lange frisst, bis alle Jobs vollständig ausgeführt sind.

  1. Erstellen Sie eine große Liste mit Dateien, z. B. [ [f0..f0-1], [fn..f2n-1]..]
  2. Verwenden Sie a ThreadPoolExecutor, um diese Liste mit allen Fäden Ihres Computers zu essen. Das kann so aussehen:
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])) 
Vielen Dank @ fabian789, dass Sie das Entwurfs-Skript der Antwort mit dem realen Arbeits-Skript bearbeitet haben, das Sie daraus gemacht haben. A. Loiseau vor 6 Jahren 1
Es ist schön, eine fruchtbare Zusammenarbeit zu sehen. +1 für die Antwort und die Frage. Kamil Maciorowski vor 6 Jahren 0
0
Friartek

using zsh to create lists for tar

Hope I understood what your trying to do. t=731 was just a number I picked out of the air. Hack as needed. The following creates multiple files with t file names or the last file with the remaining file names if not equal to 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 -- $ > /tmp/tar_file_list_${(l:5::0:)fn} (( fn++ )) done 

Use the tar command's -t or --files-from(short/long form) option to generate each tar file. This too can also be scripted.