The standard tar
command has a way to list the contents of an archive. The short form for this is tar -tf archive.tar
.
By using this together with find
, grep
, and command substitution, you get the following:
rm -f $(find . -d | head -n -1 | grep -Fv "$(tar -tf archive.tar)")
Run this in the directory where you want the contents of the archive, and replace archive.tar
with the path to the archive file.
Working from right to left for the pipeline inside the outermost command substitution:
find . -d
: Lists all the files and directories under the current directory, listing them in depth-first order. The depth-first ordering is important here, as we plan to use this file list for deletions and therefore must delete directory contents before deleting directories themselves.
head -n -1
: Exclude the last line from the find
command. This will remove the entry for /path
itself, which may or may not be present in the archive. If we weren't doing things in depth-first order, this would instead be tail -n -1
.
grep -Fv "$(tar -tf archive.tar)"
: Pass the listing of the archive to a grep command, which will then filter out those lines from the list returned by find
, so only the files which aren't' in the archive will be passed to the outter rm
command.
A couple of notes:
- This probably isn't quite POSIX compliant. It should work in GNU bash though.
- This is dependent on how tar reports the archive contents and how the archive was created. In particular, the listing has to match up with how
find
reports things. With GNU tar and most archives, it should work. If it doesn't for your case, you can probably get it to work by using either sed
or awk
on the output of the tar command inside the innermost command substitution.
- Make sure and test this before using it on production data, if it doesn't work for either of the two above reasons, it's liable to remove everything form the directory you run it in.