BusyBox tar:给出有限的磁盘空间附加解决方案?

时间:2015-03-11 16:30:22

标签: linux bash tar busybox

我在一个资源有限的Linux系统和BusyBox上 - 这个版本的tar不支持--append,-r。是否有一种解决方法,允许我[1]在[2]之后将目录B中的文件附加到目录A的现有文件tar中,使得B文件看起来来自目录A? (稍后,当有人提取文件时,它们应该最终都在同一目录A中。)

情况:我有一个我想要tar的文件列表,但我必须先处理其中的一些文件。其他进程可能会使用这些文件,因此我不想就地编辑它们。我想在使用磁盘空间时要保守,所以我的脚本只复制那些需要更改的文件(比如复制它们然后处理一些,最后用tar归档它们 - 如果我复制它们,我可能会遇到磁盘空间问题)。

这意味着我要归档的文件最终位于两个不同的位置。但我希望生成的tar文件看起来好像都在同一个位置。在我的脚本结尾附近,我最终得到了两个文本文件,按名称列出了A和B文件。

我认为这是一个完整的tar版本很简单,但我必须使用BusyBox版本(下面的用法)。提前感谢任何想法!

Usage: tar -[cxtzjaZmvO] [-X FILE] [-f TARFILE] [-C DIR] [FILE]...

Create, extract, or list files from a tar file

Operation:
   c    Create
   x    Extract
   t    List
Options:
   f    Name of TARFILE ('-' for stdin/out)
   C    Change to DIR before operation
   v    Verbose
   z    (De)compress using gzip
   j    (De)compress using bzip2
   a    (De)compress using lzma
   Z    (De)compress using compress
   O    Extract to stdout
   h    Follow symlinks
   m    Don't restore mtime
   exclude  File to exclude
   X    File with names to exclude
   T    File with names to include

2 个答案:

答案 0 :(得分:1)

原则上,您只需将包含其他文件的tar存储库附加到tar文件的末尾。它只是稍微困难一点。

tar文件包含header + file的任意数量的重复。标头始终是一个512字节的块,文件填充为512字节的倍数,因此您可以将这些单元视为可变数量的512字节块。每个街区都是独立的;它的标题以文件的完整路径名开头。因此,不要求将目录中的文件一起涂焦。

有一个并发症。在tar文件的末尾,至少有两个512字节的块完全填充0。当tar正在读取tar文件时,它将忽略一个零填充头,但第二个将导致它停止读取该文件。如果它命中EOF,它会抱怨,因此需要终止空标题。

可能有两个以上的标头,因为tar实际上是以512字节的倍数写入的块。例如,Gnu tar默认以20个512字节块的倍数写入,因此最小的tar文件通常为10240字节。

为了附加新数据,您需要先截断现有文件以消除空块。

我相信如果tar文件是由busybox生成的,那么只会有两个空块,但我没有检查过代码。这很容易;您只需要在附加其他文件之前截断文件的最后1024个字节。

对于一般的tar文件,它更棘手。如果您知道文件本身没有NUL字节(即它们都是简单的文本文件),您可以删除空标题,直到找到一个非0字节的块,这不会太多困难的。

我要做的是:

  1. 截断tar文件的最后1024个字节。
  2. 记住tar文件的当前大小。
  3. 使用简单的短消息附加包含文件tar的测试tar文件
  4. 验证tar tf是否正确显示了测试文件
  5. 将文件截断回记住的长度,
    • 如果tar tf找到了测试文件的名称,则成功
    • 如果tar文件的最后512个字节都是0,则截断文件的最后512个字节,然后返回步骤2.
    • 否则失败
  6. 如果上述过程成功,您可以继续使用新文件附加tar存储库。

    我不知道你是否有截断命令。如果没有,您可以使用dd在指定偏移量的旧文件顶部复制文件(请参阅seek=选项)。 dd将在副本末尾自动截断文件。您还可以使用dd读取512字节块(请参阅skipcount选项)。

答案 1 :(得分:0)

最好的解决方案是剪切最后1024个字节并在其后连接新的tar。为了将tar附加到现有的tar文件,它们必须是未压缩的。

对于以下文件:

$ find a b
a
a/file1
b
b/file2

你可以:

$ tar -C a -czvf a.tar.gz .
$ gunzip -c a.tar.gz | { head -c -$((512*2)); tar -C b -c .; } | gzip > a+b.tar.gz

结果:

$ tar -tzvf a+b.tar.gz 
drwxr-xr-x 0/0         0 2018-04-20 16:11:00 ./
-rw-r--r-- 0/0         0 2018-04-20 16:11:00 ./file1
drwxr-xr-x 0/0         0 2018-04-20 16:11:07 ./
-rw-r--r-- 0/0         0 2018-04-20 16:11:07 ./file2

或者你可以在同一个命令中创建两个tar:

$ tar -C a -c . | { head -c -$((512*2)); tar -C b -c .; } | gzip > a+b.tar.gz

虽然这是针对busybox tar生成的tar。如前面的回答所述,GNU tar添加了20个块的多个。您需要强制将块数设置为1(--blocking-factor = 1),以便事先知道要切割的块数:

 $ tar --blocking-factor=1 -C a -c . | { head -c -$((512*2)); tar -C b -c .; } | gzip | tar --blocking-factor=1 -tzv

无论如何,GNU tar确实有--append。只有在缩进时才会再次附加生成的tar。

,只需要最后一个--blocking-factor = 1