2

Given a tree structure with files in it, say:

source
|-- bar
|   +-- three.txt
|-- baz
|   +-- four.txt
+-- foo
    |-- one.txt
    +-- two.txt

If I do

tar czvf dest/archive-1.tgz --listed-incremental dest/archive.snar source/*

That creates a .tgz file containing all the current files and folders, just what I'd expect:

source/bar/
source/baz/
source/foo/
source/bar/three.txt
source/baz/four.txt
source/foo/one.txt
source/foo/two.txt

If I immediately do:

tar czvf dest/archive-2.tgz --listed-incremental dest/archive.snar source/*

That seems to create .tgz file containing all the subfolders of the current directory, with no files:

source/bar/
source/baz/
source/foo/

This isn't what I want. On a toy example like this one, it's not so bad, but on a large folder structure it makes it much harder to tell that the .tgz is essentially empty. It's a lot of noise. Ideally, tar would tell me that there are no updated files and exit with an error code, but even if it made an empty tar, that'd be better (for me, in this case) than an archive with lots of empty folders.

Is there any way to make tar --listed-incremental behave the way that I would like? I've done a few searches to find solutions, but I haven't found much.

I may end up just stop using --listed-incremental and doing some work with find to assemble a file list instead, but that's a lot more work if there's a way to make --listed-incremental do what I want. Any suggestions?

  • What/where was the typo? Future readers might encounter similar symptoms, so perhaps updating your post with your fix (and where) might help them? – Castaglia Mar 10 '16 at 23:26
  • I had a typo in my question that a commenter pointed out. The question has been corrected, but the problem I was experienced was unrelated to the type in the question. I don't have an answer to the question. – Geoffrey Wiseman Mar 11 '16 at 14:26
0

The manual page mentions:

When extracting from the incremental backup GNU tar attempts to restore the exact state the file system had when the archive was created. In particular, it will delete those files in the file system that did not exist in their directories when the archive was created.

To implement this they would either need a special file within the archive containing a list of all deleted files, or a copy of all directory inodes so that the relevant files can be removed. To keep in-line with the archive format it was probably cleaner for them just to include the directories rather than complicate things with an additional file.

Edited in an attempt to clarify the answer:

Example 1: Extending the original example...

Step 1: Remove one of the existing files, and create an incremental archive

$ 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/

Step 2: Recreate the previous file within foo

$ touch source/foo/two.txt

Step 3: Extract the incremental archive, which will remove the file we just created (it knows that this file was missing from the original archive as the directory entry, source/foo/, included in archive has no mention of it in its "table-of-contents")

$ tar xvfz dest/archive-3.tgz --listed-incremental dest/archive.snar
source/bar/
source/baz/
source/foo/
tar: Deleting `source/foo/two.txt'

Example 2: Including the top-level directory, where the foo directory (and it's files) will be deleted if missing from the incremental archive.

Step 1: Create the initial archive using "source" rather than "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

Step 2: Remove the foo directory and create an incremental archive that does not contain a reference to foo.

$ rm -rf source/foo
$ tar czvf dest/archive-2.tgz --listed-incremental dest/archive.snar source
source/
source/bar/
source/baz/

Step 3: Recreate the foo directory

$ mkdir source/foo
$ touch source/foo/one.txt
$ touch source/foo/two.txt

Step 4: Extract the archive (at which point foo will be deleted as it does not appear within the "table-of-contents" for the "source/" entry.

$ tar xzvf dest/archive-2.tgz --listed-incremental dest/archive.snar source
source/
tar: Deleting `source/foo'
source/bar/
source/baz/
| improve this answer | |
  • 2
    I do not find this answer completely clear. An example showing what would happen without those directories present in the archive and how the presence of the directories helps would make it a lot more clear. – kasperd May 21 '17 at 23:57
  • Furthermore, it is unclear to me whether the omission of empty directories in the incremental tar archive would causes the existing files in these directories to be deleted on the extraction side. In other words, the question is whether extracting an incremental tar holding only non-empty dirs a and b to a directory holding existing dirs a, b and c would delete directory c on the receiving side. – fredo Nov 29 '17 at 16:29
  • @kasperd, directories are simply an inode pointing to it's data blocks. These data blocks contain the "table-of-contents" of the directory - in the form of a list of inode numbers and filenames of the files assigned to the directory. – Kevin Dec 4 '19 at 21:52
  • @fredo, this one is a little more technical. If the incremental archive does not contain the directory (which would be true in the situation where the directory itself is also removed) then it would not be deleted unless the top level directory was included in the archive. In your example, c would remain. – Kevin Dec 4 '19 at 22:00
  • @fredo, in the original example, if additional directories were created within source/ then they would not be deleted during an extraction... because source/ is not included in the archive (only it's subdirectories). If the original archive was created using "tar czvf dest/archive-1.tgz --listed-incremental dest/archive.snar source" then newly created subdirectories would be removed during an extraction (as they would be missing from source/'s "table-of-contents"). – Kevin Dec 4 '19 at 22:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.