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

3 Answers 3

32

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.

6
  • It gives me this error: bash: -c: line 1: syntax error: unexpected end of file
    – aardbol
    Dec 28, 2009 at 18:46
  • @EarthMind: It works fine here. Check if the script was copied correctly.
    – Juliano
    Dec 28, 2009 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, 2009 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, 2009 at 21:44
  • @mwojtera your attempted edit should be its own answer
    – chicks
    Nov 10, 2016 at 16:53
15

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)

5
  • 1
    But then I still get the error that the given path is a directory and not a file
    – aardbol
    Dec 28, 2009 at 18:01
  • 3
    gzip alone doesn't archive directories
    – Juliano
    Dec 28, 2009 at 18:34
  • You need to tar directories before you can gzip them.
    – raphink
    Dec 28, 2009 at 18:48
  • 1
    You need tar with the z option, not straight gzip for directories. Very nice usage of find, though.
    – freiheit
    Dec 28, 2009 at 20:39
  • 3
    Error: "find: paths must precede expression: ;" The first part works, so I used (directories only): for dir in `find * -maxdepth 0 -type d`; do tar -cvzf ${dir}.tar.gz ${dir}; done
    – JosephK
    Aug 29, 2017 at 6:54
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.

3
  • 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, 2009 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, 2009 at 18:26
  • Furthermore, the first command will also make a tarball for each file in the directory.
    – raphink
    Dec 28, 2009 at 18:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .