19

How would I be able to compress subdirectories into separate archives?

Example:

directory
 subdir1
 subdir2

Should create subdir1(.tar).gz and subdir2(.tar).gz

Juliano
  • 5,402
  • 27
  • 28
aardbol
  • 1,463
  • 4
  • 17
  • 25

3 Answers3

31

This small script seems to be your best option, given your requirements:

cd directory
for dir in */
do
  base=$(basename "$dir")
  tar -czf "${base}.tar.gz" "$dir"
done

It properly handles directories with spaces in their names.

Juliano
  • 5,402
  • 27
  • 28
  • It gives me this error: bash: -c: line 1: syntax error: unexpected end of file – aardbol Dec 28 '09 at 18:46
  • @EarthMind: It works fine here. Check if the script was copied correctly. – Juliano Dec 28 '09 at 18:53
  • @EarthMind: I'm not sure you spelled out the original question well, then. You want to run this again and get new .tar.gz files while leaving the prior .tar.gz files alone? Try adding "tmstamp=$(date '+%Y%m%d-%H%M')" and change ${base} to ${base}-${tmstamp}. – freiheit Dec 28 '09 at 20:44
  • 2
    @EarthMind: if you are going to put everything in one line, make sure there is a semicolon (;) right before the tar command. Otherwise, base is passed as an environment variable to tar, instead of being a shell auxiliary variable. – Juliano Dec 28 '09 at 21:44
  • @mwojtera your attempted edit should be its own answer – chicks Nov 10 '16 at 16:53
  • anyway to speed this up, i.e. use all cores on a machine? I'm taring JPEGs for uploading so i'm not compressing (don't need `pigz`) – CpILL Nov 05 '19 at 20:43
14

How about this: find * -maxdepth 0 -type d -exec tar czvf {}.tar.gz {} \;

Explanation: You run a find on all items in the current directory. Maxdepth 0 makes it not recurse any lower than the arguments given. (In this case *, or all items in your current directory) The 'd' argument to "-type" only matches directories. Then exec runs tar on whatever matches. ({} is replaced by the matching file)

Christopher Karel
  • 6,442
  • 1
  • 26
  • 34
5

This will create a file called blah.tar.gz for each file in a directory called blah.

$ cd directory
$ for dir in `ls`; do tar -cvzf ${dir}.tar.gz ${dir}; done

If you've got more than simply directories in directory (i.e. files as well, as ls will return everything in the directory), then use this:

$ cd directory
$ for dir in `find . -maxdepth 1 -type d  | grep -v "^\.$" `; do tar -cvzf ${dir}.tar.gz ${dir}; done

The grep -v excludes the current directory which will show up in the find command by default.

Philip Reynolds
  • 9,751
  • 1
  • 32
  • 33
  • 3
    Both ls and find were NOT made to be used in this way. Specially ls, it is intended to present files in a user-readable list, not to generate file lists as arguments to 'for'. Just use `for dir in *` – Juliano Dec 28 '09 at 18:25
  • 1
    I've tried your first suggestion but it doesn't work with directories containing spaces in their name – aardbol Dec 28 '09 at 18:26
  • Furthermore, the first command will also make a tarball for each file in the directory. – raphink Dec 28 '09 at 18:45