12

I need to gzip all files in a dir separately including all files in sub-directories without deleting the originals afterwards. So let's say I have index.html, I want to have at the end index.html.gzip AND index.html.

I am able to gzip all files in my dir via

gzip -r .

But I want to keep the original files also.

Is this possible?

5 Answers 5

9
find . -type f | \
while read -r x
do
  gzip -c "$x" > "$x.gz"
done

The -c pushes the result to stdout and keeps the original alone. The disadvantage is, that you need to find the files yourself. For more sophisticated traversing, you can use find(1), however, like above: . searches starting from the current directory, and -type f returns the name of every regular file.

6
  • Why *.* in ls?
    – user332325
    Feb 15, 2011 at 9:50
  • @pooh: *.* matches all regularly named files, and usually no directories. Of course, it only works in most cases and usually not if you need it. Then use the find command.
    – Boldewyn
    Feb 15, 2011 at 11:15
  • @Boldewyn: the question was to gzip all files in a dir. ls *.* won't pick files like TODO.
    – user332325
    Feb 15, 2011 at 11:39
  • ls isn't needed at all: for x in *. However, using find should be find . -type f | while read -r x. Feb 15, 2011 at 11:51
  • Updated answer. Thanks for the -r switch on read.
    – Boldewyn
    Feb 15, 2011 at 13:17
5
find . -type f -not \( -name '*.gz' -or -name '*[~#]' \) -exec sh -c 'gzip -c "{}" > "{}.gz"' \;

You could easily switch it around to include what you want to compress ( -name '*.txt -or -name '*.html etc.) instead of like now, excluding some files (already compressed, backup and temporary files).

Handles spaces in the filename just fine too.

Change gzip to echo gzip for testing. Or skip the -exec part all together.

Edit: Oh, I forgot to mention that this doesn't check if <target>.gz already exists. This may or may not be a problem.

Edit2: Ok, here we go with something that checks for existing file. If that may be wanted. Pardon the oneliney-ness.

while read file; do if [ ! -f "$file.gz" ]; then echo "Compressing $file"; gzip -c "$file" > "$file.gz"; else echo "Not overwriting $file.gz";  fi  done < <(find . -type f -not \( -name '*.gz' -or -name '*[~#]' \))

My find-foo is maybe not what it could be, it may very well be possible to skip directly in find.

2
  • 1
    just read that -name should come before -type to avoid calling stat on every file.
    – Ben
    Jul 17, 2012 at 5:51
  • @Ben Makes sense, good input! For large trees it might be noticeable.
    – plundra
    Jul 18, 2012 at 8:06
3

gzip -k option

gzip 1.6 (June 2013) added the -k, --keep option, so now you can:

gzip -kr .

and it won't delete your original files.

Found at: https://unix.stackexchange.com/questions/46786/how-to-tell-gzip-to-keep-original-file

2

Just add the -c option, I think this should work

1
  • 1
    This probably only works when gzipping a single file at a time.
    – its_me
    Mar 30, 2013 at 5:48
0
gzip -rc `ls` > archive.gz

Tested on Debian (gzip 1.3.12-6)

1
  • That creates one archive. The OP wants separate archives. ls is unnecessary, use *. Feb 15, 2011 at 11:52

You must log in to answer this question.