Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm trying to create a compressed tarball that contains all PDF files that exist in one of my directories. The directory structure needs to be retained. Empty directories are not needed, but I really don't care if they're there.

For example, say I had a directory that looked like this:

dir
dir/subdir1
dir/subdir1/subsubdir1/song.mp3
dir/subdir2
dir/subdir2/subsubdir1
dir/subdir2/subsubdir1/document.pdf
dir/subdir2/subsubdir1/another-song.mp3
dir/subdir2/subsubdir1/top-ten-movies.txt
dir/subdir3
dir/subdir3/another-document.pdf

After running the command, I'd like to have dir.tar.gz contain this:

dir
dir/subdir2
dir/subdir2/subsubdir1
dir/subdir2/subsubdir1/document.pdf
dir/subdir3
dir/subdir3/another-document.pdf

Possible?

share|improve this question
add comment

2 Answers

up vote 10 down vote accepted

This will list all the PDFs:

$ find dir/ -name '*.pdf'
./dir/subdir2/subsubdir1/document.pdf
./dir/subdir3/another-document.pdf

You can pipe that to xargs to get it as a single space-delimited line, and feed that to tar to create the archive:

$ find dir/ -name '*.pdf' | xargs tar czf dir.tar.gz

(This way omits the empty directories)

share|improve this answer
1  
That's so awesome, thanks for the help. Here's what I came up with: find docs \( -iname '*.pdf' -o -iname '*.mp3' \) -printf '"%p"\n' | xargs tar czf docs-media.tar.gz –  Matt Alexander Jan 10 '11 at 20:26
3  
@mattalexx: Beware that this command will not work if any of the file names contain spaces or \'" (xargs's fault), and will not work if there are too many file names (the kernel's fault). –  Gilles Jan 10 '11 at 20:29
2  
@Gilles Regarding filenames with spaces and single quotes, the -printf '"%p"\n' part takes care of that (at least it did for me). –  Matt Alexander Jan 10 '11 at 20:31
1  
@Gilles Interesting about the kernel restriction. How many arguments can you have in a command in Linux? –  Matt Alexander Jan 10 '11 at 20:32
5  
Oh, on the “will not work”, note that the failure mode here is that if the command line is too long, xargs will split it up, so that the last tar invocation will silently overwrite files written by previous invocations. –  Gilles Jan 10 '11 at 20:46
show 4 more comments

With bash ≥4 or zsh and GNU tar:

tar -czf dir.tar.gz dir/**/*.pdf

This might not work if you have a very large number of PDF files and the command line is too long. Then you would need a more complex find-based solution (again, using GNU tar):

tar -cf dir.tar -T /dev/null
find dir -name '*.pdf' -exec tar -rf dir.tar {} +
gzip dir.tar

Alternatively (and portably) you can create the archive with pax.

pax -w -x ustar -s '/\.pdf$/&/' -s '/.*//' . | gzip >dir.tar.gz

The first -s says to include all .pdf files, without changing their name. The second -s says to rename all other files to an empty name, which actually means not to include them in the archive.

share|improve this answer
    
Oh yeah, I meant to mention zsh's **; I didn't even realize bash 4 had that now –  Michael Mrozek Jan 10 '11 at 20:34
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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