15

I wish to tar all files in a directory and its subdirectories that do NOT end in .jpg, .bmp, .gif, or png.

So, given the following folders and files:

foo/file.txt
foo/file.gif
foo/bar/file
foo/bar/image.jpg

I want to tar only the files file.txt and file. file.gif and image.jpg should be ignored. I would also like to maintain the folder structure.

My first thought was to pipe the results of the find command in conjunction with grep -v ".jpg|.gif|.bmp.png" to a text file, and then use the tar include argument to feed it that list of files.

However, the results of the grepped find command also contain directories (in the example above, it would be "foo" and "foo/bar"), and when a directory is fed to tar, it includes all files in that directory, so I would end up with a tar file containing all of the files--not what I want.

Is there any way to prevent find from outputting directories? Is there a far easier way to approach this?

asked Jun 26, 2011 at 15:52
1
  • While John's solution is much more elegant (and most likely more efficient), if you want to only list files using find, you can use the type argument with the parameter f as follows: find -type f | egrep -v "bmp|png|gif|jpg" Commented Jun 26, 2011 at 16:48

2 Answers 2

32

Use --exclude=pattern option:

tar --exclude='*.jpg' --exclude='*.png' --exclude='*.bmp' --exclude='*.gif' -cvf tar-filename.tar folder
answered Jun 26, 2011 at 16:05
2
  • I knew I was overcomplicating things. Thanks. Commented Jun 26, 2011 at 16:06
  • 1
    As a hint, make sure --exclude is set before -cvf Commented Jul 13, 2021 at 3:50
6

I think the most elegant way to remove multiple files type is using what is called brace expansion.

How does brace expansion work?

Brace expansion allows you to create multiple strings from patterns within a brace, where each pattern is separated by a comma. For instance, the command

echo Front-{A,B,C}-Back

will yield

Front-A-Back Front-B-Back Front-C-Back

Simple like that :) You can also expand a range of integers using the following notation

echo {001..15}

How to use brace expansion to solve your problem?

Try it:

tar --exclude={'*.jpg','*.png','*.bmp','*.gif'} -cvf tar-filename.tar folder

If you want to check out what is going on, just echo this last command and you will notice that it produces

tar --exclude=*.jpg --exclude=*.png --exclude=*.bmp --exclude=*.gif -cvf tar-filename.tar folder

Both ways are correct, but mine is much more readable and compact :)

music2myear
52.9k57 gold badges106 silver badges154 bronze badges
answered Mar 25, 2022 at 22:03
1
  • 2
    That is a very nice addition for the existing answer. Commented Mar 25, 2022 at 22:17

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.