给定一个包含文件的树结构,说:
source
|-- bar
| +-- three.txt
|-- baz
| +-- four.txt
+-- foo
|-- one.txt
+-- two.txt
如果我做
tar czvf dest/archive-1.tgz --listed-incremental dest/archive.snar source/*
这将创建一个.tgz
包含所有当前文件和文件夹的文件,正如我所期望的:
source/bar/
source/baz/
source/foo/
source/bar/three.txt
source/baz/four.txt
source/foo/one.txt
source/foo/two.txt
如果我立即这样做:
tar czvf dest/archive-2.tgz --listed-incremental dest/archive.snar source/*
这似乎创建了.tgz
包含当前目录的所有子文件夹但没有文件的文件:
source/bar/
source/baz/
source/foo/
这不是我想要的。在像这样的玩具示例中,情况还不算太糟,但在大型文件夹结构中,很难判断 .tgz 本质上是空的。噪音很大。理想情况下,它会tar
告诉我没有更新的文件并以错误代码退出,但即使它生成了一个空的 tar,这也比包含许多空文件夹的存档要好(对我来说,在这种情况下)。
有什么方法可以让它tar --listed-incremental
按照我想要的方式运行吗?我搜索了几次以寻找解决方案,但没有找到太多。
我可能最终会停止使用--listed-incremental
,而是做一些工作来find
汇编文件列表,但如果有办法实现我想要的效果,那么工作量就会大得多--listed-incremental
。有什么建议吗?
答案1
手册页提到:
从增量备份中提取时,GNU tar 会尝试恢复创建存档时文件系统的准确状态。具体来说,它将删除文件系统中那些在创建存档时目录中不存在的文件。
为了实现这一点,他们要么需要在档案中有一个包含所有已删除文件列表的特殊文件,要么需要一份所有目录 inode 的副本,以便删除相关文件。为了与档案格式保持一致,对他们来说,只包含目录可能更简洁,而不是用额外的文件让事情变得复杂。
经过编辑试图澄清答案:
示例 1:扩展原始示例...
步骤 1:删除其中一个现有文件,并创建增量存档
$ rm source/foo/two.txt
rm: remove regular empty file `source/foo/two.txt'? y
$ tar czvf dest/archive-3.tgz --listed-incremental dest/archive.snar source/*
source/bar/
source/baz/
source/foo/
步骤 2:在 foo 中重新创建先前的文件
$ touch source/foo/two.txt
步骤 3:提取增量存档,这将删除我们刚刚创建的文件(它知道原始存档中缺少此文件,因为存档中包含的目录条目 source/foo/ 在其“目录”中没有提及它)
$ tar xvfz dest/archive-3.tgz --listed-incremental dest/archive.snar
source/bar/
source/baz/
source/foo/
tar: Deleting `source/foo/two.txt'
示例 2:包括顶级目录,如果增量存档中缺少 foo 目录(及其文件),则会将其删除。
步骤 1:使用“source”而不是“source/*”创建初始档案
$ tar czvf dest/archive-1.tgz --listed-incremental dest/archive.snar source
source/
source/bar/
source/baz/
source/foo/
source/bar/three.txt
source/baz/four.txt
source/foo/one.txt
source/foo/two.txt
第 2 步:删除 foo 目录并创建不包含对 foo 的引用的增量存档。
$ rm -rf source/foo
$ tar czvf dest/archive-2.tgz --listed-incremental dest/archive.snar source
source/
source/bar/
source/baz/
步骤 3:重新创建 foo 目录
$ mkdir source/foo
$ touch source/foo/one.txt
$ touch source/foo/two.txt
步骤 4:提取档案(此时 foo 将被删除,因为它没有出现在“source/”条目的“目录”中)。
$ tar xzvf dest/archive-2.tgz --listed-incremental dest/archive.snar source
source/
tar: Deleting `source/foo'
source/bar/
source/baz/