Bash 脚本将大约 1GB 的文件打包到 tar 存档中

Bash 脚本将大约 1GB 的文件打包到 tar 存档中

我有几个包含数千个文件的文件夹,每个文件夹的大小大约为 3 - 10GB。现在,我想将这些文件打包到文件夹内,每个 tar 文件的大小应约为 1GB。之后,我想使用 Python 来处理这些 tar 文件。

#!/bin/bash

dirlist=$(find $1 -mindepth 1 -maxdepth 1 -type d)
stored_date=$(date +%Y-%m-%d --date="-1 day")
#stored_date='2019-10-23'

for dir in $dirlist
do
(
    cd $dir
    tar_file=${PWD##*/}  
    tar_file="${tar_file}_${stored_date}.tar"

    echo "${tar_file}"

    tar -c $stored_date*.html --tape-length=1000M  -f ${tar_file}  --remove-files
)
done

它可以很好地创建 1GB 块 - 但使用“--tape-length”选项时,Python 会遇到各种问题

tarfile.ReadError:数据意外结束

(另外:我也想使用 Python 来处理在 tar 存档边缘分割的文件)

Linux 有解决这个问题的方法吗?我发现 star 而不是 tar,但还没有尝试过 - 如果可能的话,我更愿意使用标准 tar。

答案1

在每个目录循环中嵌套第二个循环以在将每个文件附加到 tar 文件之前跟踪每个文件的大小怎么样?这是我的意思的示意性伪代码:

max_size=$((1024*1024*1024))
total_size=0
for dir in $dirlist ; do
  for foo in $dir/*; do
    this_size="$(stat -c"%s" $foo)"
    if [ $(($total_size + $this_size)) -le $max_size ] ; then
      tar --append ... $foo
      total_size="$(($total_size + $this_size))"
    else
      # start new tar file here
      tar -c ... $foo
      total_size="$this_size"
    fi
  done
done

答案2

据我所知,python 不理解 tar 格式,因此您可能喜欢使用可能与 tar 存档标准不 100% 兼容的 tar 存档模块。这是一个需要考虑的重要事项,有许多半生不熟的 tar 实现通常仅支持官方功能集的子集。

我建议在不进入模式的情况下使用该star选项。这可以防止在中间分割文件,但无法归档大于指定磁带大小的文件。-tsizestarmulti volumestar

如果默认 shell“sh”在支持“$((expr))”方面符合 POSIX,否则将“sh -c”替换为“ksh -c”或类似的。

...怎么样:

cd /tmp
star -C path/to/archivedir -c tsize=1G \
new-volume-script='cd /tmp;sh -c "mv vol-last.tar vol\$((\$1-1)).tar" script' \
f=vol-last.tar .

这会将创建的 TAR 存档保留在 /tmp 中。您需要手动将 vol-last.tar 重命名为最终预期的卷号。我可能会考虑增强 star 以将新卷脚本运行到每个存档的末尾,包括最后一个。

相关内容