0

I want tar to pack a complete directory

tar cvjf dir.tbz dir

But make it delete all files

tar cvjf dir.tbz dir --remove-files

However this removes ./dir too. So I tried to cd into directory before packing

tar cvjf dir.tbz --remove-files -C dir .

But that still removes ./dir... what does not make any sense to me, because why should tar delete the working directory itself? Can't I pack a complete directory and remove the files after packing without deleting the whole directory?

I have a process running, that constantly creates files in ./dir and want to pack all files each hour and then remove these that are packed. I could mkdir after tar and delete but that could cause the other process that creates files struggle when it tries to write a new file before mkdir had recreated the directory.

  • You still have race issues: what happens if the process creates a file while tar is working? A valid solution would be to use a lock file outside dir, and make both tar and the process lock the file while running. Then, you can use --remove-files and mkdir before unlocking and there will be no race conditions. – user49740 May 6 '15 at 14:52
  • Alternatively, you could sidestep the problem by chowning dir to another user, while still giving the process and tar permissions to read/write it via the group or via ACLs. Then, tar will not be able to delete it. The races in the previous comment still apply. – user49740 May 6 '15 at 14:55
  • The locking wouldn't work, since tar takes significantly longer than the writing process which creates a file each 2s and tar can take longer than that, result when tar locked: I would lose snapshots. – fdafgfdgfagfdagfdagfdagfdagfda May 6 '15 at 15:11
1

You could try something like this:

find dir -type f -mmin +1 | xargs -I{} sh -c 'tar rvf dir.tar {} && rm {}'
bzip2 dir.tar && mv dir.tar.bz2 dir-$(date +%F-%T).tbz

It's a bit more complicated than your current command, but works and I don't believe it has any race issues (provided a file isn't written to multiple times with gaps longer than a minute).

The find command finds all files in dir that are at least one minute old (so not currently being written to). This list is then piped to xargs, which adds each in turn to the dir.tar file. Once the file has been successfully added to the tar file, the original is removed. Doing it one at a time avoids issues with having too long command lines if you have a large number of files. Finally you can compress and rename the tar file.

  • I can accept that solution, however I wonder why you use a seperate bzip2 and then move it and not bzip within tar in one step? – fdafgfdgfagfdagfdagfdagfdagfda May 7 '15 at 9:16
  • Because you can't append files to a compressed tar file. – TheBamf May 10 '15 at 8:05
0

My workaround to this would be the following now:

I write a script that cds into the directory and tars the stuff using ./* then deletes. I was just hoping, that -C would do the same so I could have it in one command line but it doesn't.

#!/bin/bash

cd /path/to/dir
tar cvjf dir.tbz ./* --remove-files

Should work.

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.