Создайте много файлов tar из каталога с 500000 файлами

392
fabian789

У меня есть каталог, содержащий около 500 тыс. Файлов, и я хочу разделить их на ttar-файлы.

Скажем формально, давайте назовем файлы file_0, ..., file_, где Nоколо 500к. Я хочу создать ttar-файлы, каждый из которых содержит T=N/tфайлы, где i-й tar-файл содержит

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

Какой эффективный способ сделать это? Я собирался написать скрипт Python, который просто перебирает Nфайлы и делит их на tпапки, а затем вызывает tarв каждой, но это кажется очень неоптимальным. У меня много ядер на сервере, и я чувствую, что это должно происходить параллельно.

2
`xjobs` имеет опцию` -l`, чтобы объединить несколько входных аргументов для каждого задания. Вы должны будете отдельно подсчитать файлы и поделить на `N` до этого. Toby Speight 7 лет назад 0

2 ответа на вопрос

4
A. Loiseau

Вы можете использовать concurrentбиблиотеку Python, которая предназначена для обработки очереди запросов среди всех или некоторых потоков, поедая очередь до тех пор, пока все задания не будут полностью выполнены.

  1. Создайте большой список файлов, например, [ [f0..f0-1], [fn..f2n-1]..]
  2. Используйте ThreadPoolExecutorэтот список со всеми многочисленными нитями вашего компьютера. Это может выглядеть так:
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])) 
Спасибо @ fabian789 за то, что вы отредактировали черновой сценарий ответа с реальным рабочим, который вы из него сделали. A. Loiseau 7 лет назад 1
Приятно видеть плодотворное сотрудничество. +1 за ответ и вопрос. Kamil Maciorowski 7 лет назад 0
0
Friartek

используя zsh для создания списков для tar

Надеюсь, я понял, что ты пытаешься сделать. t=731был просто номер, который я выбрал из воздуха. Взломать по мере необходимости. Следующее создает несколько файлов с tименами файлов или последний файл с оставшимися именами файлов, если они не равны 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 

Используйте tarкоманду -tили --files-from(краткую / длинную форму) для создания каждого файла tar. Это тоже может быть в сценарии.

Похожие вопросы