Saturday, January 29, 2011

Linux gzip multiple subdirectories into separate archives?

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

Example:

directory
 subdir1
 subdir2

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

  • 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)

    EarthMind : But then I still get the error that the given path is a directory and not a file
    Juliano : gzip alone doesn't archive directories
    Raphink : You need to tar directories before you can gzip them.
    freiheit : You need tar with the z option, not straight gzip for directories. Very nice usage of find, though.
  • 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.

    Juliano : 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 *`
    EarthMind : I've tried your first suggestion but it doesn't work with directories containing spaces in their name
    Raphink : Furthermore, the first command will also make a tarball for each file in the directory.
    From Phil
  • 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.

    EarthMind : It gives me this error: bash: -c: line 1: syntax error: unexpected end of file
    Juliano : @EarthMind: It works fine here. Check if the script was copied correctly.
    freiheit : @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}.
    Juliano : @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.
    From Juliano

0 comments:

Post a Comment