How to combine the 'tar' command with 'find'

You can use something like:

find var/log -iname 'anaconda.*' -print0 | tar -cvf somefile.tar --null -T -

The -print0 and -T work together to allow filenames with spaces newlines, etc. The final - tells tar to read the input filenames from stdin.

Note that -print0 must come at the end of your statement, per this answer. Otherwise you will probably get more files than you expect.


Note: See @Iain's answer for a somewhat more efficient solution.

Note that find will call the -exec action for every single file it finds.

If you run tar -cvf file.tar {} for every single file find outputs, this means you'll overwrite file.tar every time, which explains why you end up with one archive left that only contains anaconda.storage.log — it's the last file find outputs.

Now, you actually want to append the files to the archive instead of creating it each time (this is what the -c option does). So, use the following:

find var/log/ -iname "anaconda.*" -exec tar -rvf file.tar {} \;

The -r option appends to the archive instead of recreating it every time.

Note: Replace -iname anaconda.* with -iname "anaconda.*". The asterisk is a wildcard and can be expanded by your shell before find even sees it. To prevent this expansion, wrap the argument in double quotes.


As for tar removing leading /: The archive should only contain relative file names. If you added files with a leading /, they would be stored as absolute file names, literally meaning /var/… on your computer, for example.

IIRC this is simply a precaution for tar implementations other than GNU, and it's safer this way because you won't overwrite your actual data in /var/… when you extract the archive if it contains relative filenames.


Try this:

tar -cvf file.tar `find var/log/ -iname "anaconda.*"`

You were trying to use find to -exec tar. But the way the -exec option works, it runs that command once for each matching file it finds, causing tar to overwrite the tar file it produces each time. That's why you only ended up with the last one. Also, you need to put quotes around the pattern you specify to find so that the shell doesn't expand it before passing it to find.

Using command substitution with backticks (or using $(...) notation if you prefer), the entire list of names produced by find is pasted back onto the command line as arguments to tar, causing it to write them all at once.