34

How do I compress every file in a directory into its own tar whilst preserving the name for each file?

i.e. file1.out file2.out

-->

file1.out.tar.gz file2.out.tar.gz

DD.
  • 3,024
  • 10
  • 34
  • 50

3 Answers3

77

Putting every file into a separate tar file doesn't make any sense in this scenario. You can use gzip to compress them directly:

gzip *

will result in file1.out.gz, file2.out.gz etc.

You would use tar only if you would need a compressed archive as a single file.

If you ineed need a tar archive for every file, you can create it like so:

for i in *; do tar -czf $i.tar.gz $i; done
Sven
  • 97,248
  • 13
  • 177
  • 225
  • 7
    +1 - There is no reason to create a tar (Tape ARchive) for a single file. Just compress what you want to compress - the result will be marginally smaller, and make infinitely more sense to people extracting the files. – voretaq7 Feb 05 '12 at 20:28
  • To tar each individual subdirectory (only one level deep) and remove the original: `find . -maxdepth 1 -type d ! -path . | while read a_dir; do tar -zcvf ${a_dir}.tgz ${a_dir} --remove-files; done` – xb. Jul 13 '16 at 18:21
  • (can't edit my comment above after 5 min) A simpler/safer version: `find . -maxdepth 1 -mindepth 1 -type d -exec tar -zcvf {}.tgz {} --remove-files \;` – xb. Jul 13 '16 at 18:37
  • And `gzip -d *` to unzip `.gz` files – igonejack Apr 27 '21 at 02:43
11

To build on @SvenW's answer (which will only work on the current directory), if you have a HUGE number of files or want to do it on a recursive directory structure you can also use

find . -type f -exec gzip \{\} \;

and if you need to put the output into a different directory (in this example, ../target) and don't want to remove the originals, you can do something like:

find . -type f -print | while read fname ; do
    mkdir -p "../target/`dirname \"$fname\"`"
    gzip -c "$fname" > "../target/$fname.gz"
done
fluffy
  • 292
  • 1
  • 8
  • 1
    `find . -type f -exec gzip {} \;` will be sufficient. The second code will fail with filenames containing spaces and the like. – user unknown Feb 06 '12 at 02:29
  • Some shells don't like bare {}s, and the second one does something markedly different than the first (and I was aware of the spacing issues but that is kind of tricky to deal with). – fluffy Feb 06 '12 at 03:07
  • If you know such a shell, I invite you to answer my question over here: http://unix.stackexchange.com/questions/8647/gnu-find-and-masking-the-for-some-shells-which . Nobody was able to name something which is today in use so far. If you are aware of a risk of your answer, it might be a good idea to name it in your answer. – user unknown Feb 06 '12 at 04:20
  • @userunknown I was brought up on (t)csh, which had quite a lot of trouble with unescaped curly braces at one time, although it doesn't appear to anymore (but I still escape `{}` as a force of habit). Others have already posted those as answers to your question, however. – fluffy Feb 06 '12 at 06:55
  • Or, to compress all non-binary files: `find . -type f -exec grep -Iq . {} \; -and -exec gzip {} \;` – xb. Jul 13 '16 at 15:30
  • A parallel version of the command in my comment above: `find . -type f -exec grep -Iq . {} \; -and -print0 | xargs -0 -n 1 -P 16 gzip` running on 16 CPUs, for instance. – xb. Jul 13 '16 at 19:25
1

Try this one:

#!/bin/bash
for fich in *; do
    if [ "$fich" != "*" ] ; then
        gzip -9 -c $fich > $fich.tar.gz
        \mv $fich.tar.gz $fich
    fi
done
alexander.polomodov
  • 1,060
  • 3
  • 10
  • 14
Mats
  • 11
  • 1