Ask Ubuntu is a question and answer site for Ubuntu users and developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to gzip all files on ubuntu that have the file extension .css, .html or .js. in a top directory and all subdirectories. I want to keep the original files and overwrite the .gz file, if already existing.

So when I have n files, I want to keep these n files and create additional n archive files. Not just one.

My try was to run a script that looks like this:

gzip -rkf *.css
gzip -rkf *.html
... one line for each file extension

First: I need to have one line in that script for each file extension I want to gzip. That's ok, but I hope to find a better way

Second and more important: It does not work. Although -r should do the job, the subdirectories are unchanged. The gzip file is only created in the top directory.

What am I missing here?

Btw: The following is a bug in the verbose output, right? When using -k and -v option

-k, --keep        keep (don't delete) input files
-v, --verbose     verbose mode

The verbose output says it replaces the file, although "replace" means that the original file does not exist after the replace. Anyway, THis is only the output thing.

$ ls
  index.html      subdir1  testfile      testfile.css.gz  subdir2  testfile.css
$ gzip -fkv *.css
  testfile.css:   6.6% -- replaced with testfile.css.gz
$ ls
  index.html      subdir1  testfile      testfile.css.gz  subdir2  testfile.css
share|improve this question
-r works as designed. From man gzip: Travel the directory structure recursively. If any of the file names specified on the command line are directories, gzip will descend into the directory and compress all the files it finds there (or decompress them in the case of gunzip). (emphasis mine) – Dennis Jul 11 '14 at 20:34
Ok. So -r would enter a directory with the name XYZ.css. Then recursion is not designed as I expected. – Sadik Jul 12 '14 at 8:59
up vote 5 down vote accepted

you can do that with a for loop to find every file then compress it:

for i in `find | grep -E "\.css$|\.html$"`; do gzip "$i" ; done
share|improve this answer
Thank you! Though the -r option does not work, -k and -f are working, so I can use them like this: for i in find | grep -E "\.css$|\.html$"; do gzip -vkf "$i" ; done` – Sadik Jul 11 '14 at 12:19
@Sadik: Be careful! This approach won't work if any of the files' names contains a space. – Dennis Jul 11 '14 at 20:31
Could you explain why not? – Sadik Jul 12 '14 at 9:13
@Sadik: `...` provides a string, not a list. for uses the internal field separator ($IFS) to decide where that string should be split. By default, it splits at linefeeds, tabs and spaces, so if you have a file called new style.css, the commands gzip new and gzip style.css will be executed. – Dennis Jul 12 '14 at 13:01
@Sadik, Dennis is right, as quick workaround you can run export IFS=$'\n' just before the for loop. – mndo Aug 8 '14 at 14:52

I would use

find /path/to/dir \( -name '*.css' -o -name '*.html' \) -exec gzip --verbose --keep {} \;

Change name to iname if you want to match the extensions case-insensitively (i.e. include .CSS and/or .HTML extensions). You can omit the /path/to/dir if you want to start the recursive search from the current directory.

share|improve this answer

To get the list of files:

find -type f | grep -P '\.js|\.html|\.css'

And to gzip all those files:

find -type f | grep -P '\.js|\.html|\.css' | tar cvzf archive.gz -T -
share|improve this answer
Wouldn't this tar the list of files as output by find, rather than the files themselves? – Jos Jul 11 '14 at 12:15
I edited my question to make clear that I want to have an archive file for each css,html or js file. – Sadik Jul 11 '14 at 12:16
@Jos no with the -T option tar processes the input as filenames. – chaos Jul 11 '14 at 12:25
@chaos Ah, thank you. I learned something today. – Jos Jul 11 '14 at 12:31

I used the SteelDriver's answer, but like to complete it by these options, cd into any folder and type this code, all your files matching will be gzipped

find \( -name '*.css' -o -name '*.js' \) -exec gzip --verbose --keep --best --force {} \;

--best for best compression ratio --force for not asking and overwriting if there is already a gzipped file

share|improve this answer

Your Answer


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.