270

I would like to compress a text file using gzip command line tool while keeping the original file. By default running the following command

gzip file.txt 

results in modifying this file and renaming it file.txt.gz. instead of this behavior I would like to have this new compressed file in addition to the existing one file.txt. For now I am using the following command to do that

gzip -c file.txt > file.txt.gz 

It works but I am wondering why there is no easier solution to do such a common task ? Maybe I missed the option doing that ?

4
  • 3
    This is because, gzip compresses the given file and creates new file. Compression means squeezing original file and replacing it with new one. Your "-c" option is explicitly telling gzip to save it with other name. That's why it works Commented Aug 31, 2012 at 8:52
  • @SHW I didn't get your comment ... ? Commented Aug 31, 2012 at 9:07
  • @ManuelSelva once the original file is compressed, it's no longer needed, I guess that was the design. Commented Aug 31, 2012 at 9:58
  • 5
    Why gzip/gunzip do this by default when no other unix tool does this is beyond me. Commented Nov 29, 2018 at 7:09

4 Answers 4

294

For GNU gzip 1.6 or above, FreeBSD and derivatives or recent versions of NetBSD, see don_cristi's answer.

With any version, you can use shell redirections as in:

gzip < file.txt > file.txt.gz 

When not given any argument, gzip reads its standard input, compresses it and writes the compressed version to its standard output. As a bonus, when using shell redirections, you don't have to worry about files called "--help" or "-" (that latter one still being a problem for gzip -c --).

Another benefit over gzip -c file.txt > file.txt.gz is that if file.txt can't be opened, the command will fail without creating an empty file.txt.gz (or overwriting an existing file.txt.gz) and without running gzip at all.

A significant difference compared to gzip -k though is that there will be no attempt at copying the file.txt's metadata (ownership, permissions, modification time, name of uncompressed file) to file.txt.gz.

Also if file.txt.gz already existed, it will silently override it unless you have turned the noclobber option on in your shell (with set -o noclobber for instance in POSIX shells).

9
  • 4
    Now this addresses the specifics of the OP's question and answers the general question "How to tell gzip to keep the original file". Very handy and more useful than -c. Commented Dec 18, 2012 at 21:20
  • 14
    Note that the < and > are actually supposed to be typed into the command and are not representing a placeholder for the filename Commented Feb 23, 2015 at 11:32
  • 2
    What's the -k option? Couldn't find it in the man pages, e.g. this version here linux.die.net/man/1/gzip. Also, it looks like gzip copies the file's metadata by default. Commented Jun 29, 2018 at 18:15
  • 1
    @flow2k, that's the link to don_cristi's answer. Commented Jun 29, 2018 at 21:46
  • 1
    @StéphaneChazelas Working on gzip version 1.4 as well. cat file | gzip > file.gz Commented Jun 23, 2019 at 12:30
187

Note that the recently (June 2013) released gzip-1.6 "accepts the --keep (-k) option, for consistency with tools like xz, lzip and bzip2. With this option, gzip no longer removes named input files when compressing or decompressing".

Excerpt from the man page:

 -k --keep Keep (don't delete) input files during compression or decompression. 

So, as of 1.6, you can use -k or --keep to keep the original file:

gzip -k -- "$file" 

(note that it doesn't work if $file is - (which gzip interprets as meaning stdin instead of the actual file called -), in which case, you have to change it to ./-)

That option was first introduced in the FreeBSD implementation of gzip (in FreeBSD 7.0 in 2007) for consistency with bzip2. That gzip is based on a rewrite of GNU gzip by NetBSD. The -k option eventually made it back to NetBSD in 2010.

6
  • 13
    Geez. RHEL6 only comes with zip 1.3.12 in base... Commented Jun 25, 2013 at 14:36
  • This works on Mac/OS X :) (which is BSD) Commented Jun 29, 2016 at 23:56
  • 1
    What is "--" for? I think gzip -k "file" works fine. Commented Sep 19, 2018 at 18:04
  • 3
    @notilas see unix.stackexchange.com/q/11376/22142 Commented Sep 19, 2018 at 18:30
  • 1
    @MichaelChirico CentOS 7. :( Commented Mar 27, 2019 at 14:06
31

From the documentation it seems that there is no option to create a copy of the file.

You can define a shell function

gzipkeep() { if [ -f "$1" ] ; then gzip -c -- "$1" > "$1.gz" fi } 

and then

gzipkeep file.txt 
2
  • 2
    Note that if the file is -, you have to call it as gzipkeep ./-. Commented Jan 7, 2014 at 17:13
  • This is the best solution for scripts IMO, as you can be sure the output file > "$1.gz" will exist exactly like specified. Furthermore, you can also specify a different name if the need should arise. Commented Sep 19, 2020 at 8:10
0

To build on @Matteo's answer, you could make gzipkeep able to handle wildcards by surrounding the code in a for loop, preserving the ability that gzip has to handle multiple files at once on a system that lacks that -k flag (a huge advantage, otherwise, for -k). I also made it verbose so I could see the status of each attempted file:

gzipkeep() { for file in "$@"; do if [ -f "$file" ] ; then gzip -cv9 -- "$file" > "$file.gz" fi done } 

Then just run it with a wildcard. For example:

gzipkeep images/*.svg 

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.