views:

197

answers:

8

Hi all,

I try to tar.gz a directory and use

tar -czf workspace.tar.gz *

The resulting tar includes .svn directories in subdirs but NOT in the current directory (as * gets expanded to only 'visible' files before it is passed to tar

I tried to

tar -czf workspace.tar.gz . instead but then I am getting an error because '.' has changed while reading:

tar: ./workspace.tar.gz: file changed as we read it

Is there a trick so that * matches all files (including dot-prefixed) in a directory?

(using bash on Linux SLES-11 (2.6.27.19)

+2  A: 

You can include the hidden directories by going back a directory and doing:

cd ..
tar -czf workspace.tar.gz workspace

Assuming the directory you wanted to gzip was called workspace.

bramp
And this avoids the changing file problem too.
Jonathan Leffler
+2  A: 

If you really don't want to include top directory in the tarball (and that's generally bad idea):

tar czf workspace.tar.gz -C /path/to/workspace .
rkhayrov
I am in need to exclude the top directory and I am in need to place the tar in the base directory.
Micha
A: 

A good question. In ZSH you can use the globbing modifier (D), which stands for "dotfiles". Compare:

ls $HOME/*

and

ls $HOME/*(D)

This correctly excludes the special directory entries . and ... In Bash you can use .* to include the dotfiles explicitly:

ls $HOME/* $HOME/.*

But that includes . and .. as well, so it's not what you were looking for. I'm sure there's some way to make * match dotfiles in bash, too.

loevborg
+1  A: 

Update: I added a fix for the OP's comment.

tar -czf workspace.tar.gz .

will indeed change the current directory, but why not place the file somewhere else?

tar -czf somewhereelse/workspace.tar.gz .
mv somewhereelse/workspace.tar.gz . # Update
Peter Jaric
The file will be processed afterwards and is required to be in the workspace - it is a little bid ugly but it is just needed (the whole thing ist just a workaround ...)
Micha
OK, I'll add a fix for that :)
Peter Jaric
And if you need to be able to run this repeatedly, add 'rm workspace.tar.gz' before the tar line.
Peter Jaric
+1  A: 

You can fix the . form by using --exclude:

tar -czf workspace.tar.gz --exclude=workspace.tar.gz .
caf
A: 
tar -czf workspace.tar.gz .??* *

Specifying .??* will include "dot" files and directories that have at least 2 characters after the dot. The down side is it will not include files/directories with a single character after the dot, such as .a, if there are any.

Scott Thomson
A: 

Thanks all,

at the end I Peters solution leads the way

Regards Michael

Micha
OK - so you tell everyone else that by logging in with the ID that you used to create the question, and then accepting the answer. That awards Peter, and you gain a little too, and let's everyone know what your preferred answer is (or the answer that was most useful to you).
Jonathan Leffler
I couldn't agree more :)
Peter Jaric
+1  A: 

Don't create the tar file in the directory you are packing up:

tar -czf /tmp/workspace.tar.gz .

does the trick, except it will extract the files all over the current directory when you unpack. Better to do:

cd ..
tar -czf workspace.tar.gz workspace

or, if you don't know the name of the directory you were in:

base=$(basename $PWD)
cd ..
tar -czf $base.tar.gz $base

(This assumes that you didn't follow symlinks to get to where you are and that the shell doesn't try to second guess you by jumping backwards through a symlink - bash is not trustworthy in this respect. If you have to worry about that, use cd -P .. to do a physical change directory. Stupid that it is not the default behaviour in my view - confusing, at least, for those for whom cd .. never had any alternative meaning.)


One comment in the discussion says:

I [...] need to exclude the top directory and I [...] need to place the tar in the base directory.

The first part of the comment does not make much sense - if the tar file contains the current directory, it won't be created when you extract file from that archive because, by definition, the current directory already exists (except in very weird circumstances).

The second part of the comment can be dealt with in one of two ways:

  1. Either: create the file somewhere else - /tmp is one possible location - and then move it back to the original location after it is complete.
  2. Or: if you are using GNU Tar, use the --exclude=workspace.tar.gz option. The string after the = is a pattern - the example is the simplest pattern - an exact match. You might need to specify --exclude=./workspace.tar.gz if you are working in the current directory contrary to recommendations; you might need to specify --exclude=workspace/workspace.tar.gz if you are working up one level as suggested. If you have multiple tar files to exclude, use '*', as in --exclude=./*.gz.
Jonathan Leffler
A very good summary of the previous answers.
Peter Jaric