从包含 500000 个文件的目录中创建许多 tar 文件

从包含 500000 个文件的目录中创建许多 tar 文件

我有一个包含大约 500k 个文件的目录,想要将它们切分成ttar 文件。

正式地说,我们称这些文件file_0, ..., file_{N-1}为 ,N大约 500k。我想创建ttar 文件,每个文件包含T=N/t文件,其中第 i 个 tar 文件包含

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

有什么有效的方法可以做到这一点?我本来打算编写一个 Python 脚本,循环遍历文件N并将它们分成t文件夹,然后调用tar每个文件夹,但这感觉非常不理想。我的服务器上有很多核心,我觉得这应该并行发生。

答案1

您可以使用 pythonconcurrent库,该库旨在处理所有或部分线程之间的请求队列,并使用该队列直到所有作业完全执行。

  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]))

答案2

使用 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 -- ${VarSorted[$i,$i+$t-1]} > /tmp/tar_file_list_${(l:5::0:)fn}
  (( fn++ ))
done

使用tar命令的-t--files-from(短/长格式)选项来生成每个 tar 文件。这也可以用脚本来编写。

相关内容