8

tar czf dist.tgz --exclude=".gitignore" .

This creates files in tar with leading "./" which later turns to problem when server needs to extract parts of tar.

Could someone tell me how to pack it so that wont have leading "./"?

3
  • 3
    Why is the leading ./ a problem?
    – chutz
    Dec 12, 2012 at 15:46
  • 1
    Take * instead of ., unless you need to include files and directories in the current dir starting with dot.
    – ott--
    Dec 12, 2012 at 16:29
  • 1
    @chutz --strip-components counts it. So stripping 1 on ./a/b -> a/b but a/b -> b. Jan 10, 2019 at 10:19

6 Answers 6

9

Try the --xform option, which uses a sed-like replace expression. This allows you to change the path references going into the archive rather than handle it during the extraction (such as with the --strip-components).

tar --exclude=.gitignore -cz --xform s:'./':: -f dist.tgz ./

To list the files as they are processed, add the -v and --show-transformed-name options:

tar --exclude=.gitignore -cvz --xform s:'./':: --show-transformed-name -f dist.tgz ./

The argument to pass --xform follows this structure: s/regexp/replace/[flags] Note that in my example, I used : as a delimter; you can use any character you want so long as you use it consistently. Good reference here.

4
  • 2
    If you don't have a tar with --xform, then you might have the pax(1) command instead, which has a similar option.
    – Phil P
    Oct 9, 2013 at 18:33
  • 1
    --xform s:'./':: didn't work for me, the dot was still there
    – user448564
    Jan 5, 2018 at 17:39
  • I had to do this: s:\\./\\?:: (without the question mark then the . directory would still be there albeit empty)
    – user448564
    Jan 5, 2018 at 17:40
  • This breaks symlinks
    – user448564
    Jan 5, 2018 at 17:58
8

There are a number of ways to accomplish this, many of which have already been hinted at in this question, some of which have not. This is my attempt to compile them all (with references) and show examples for easy reading, allowing the reader to pick and choose one to fit his or her needs.


Example Input Tree

This is the structure that’s going to be tar’d up in the following examples.

.dotfile
dir/
  .hidden
  file.txt
root.txt

POSIX (Cross-Platform, Cross-Shell) Solution

You may be able to use use pax instead of tar, as Phil P. pointed out.

Usual behavior:

$ pax -wzvf ../ball.tar.gz .
[…]
$ pax -zf ../ball.tar.gz
.
./.dotfile
./dir
./dir/.hidden
./dir/file.txt
./root.txt

No dot-slash:

$ pax -wzvf ../ball.tar.gz -s ':^\./::' .
[…]
$ pax -zf ../ball.tar.gz
.
.dotfile
dir
dir/.hidden
dir/file.txt
root.txt

Shell Globbing (Cross-Platform) Solution

You may also be able to use * instead of ., as ott-- pointed out. This solution is basically a short-hand form of chutz’s answer, since the shell will expand the asterisk in the example below to all non-hidden files before passing them along as arguments to the tar program.

No dot-slash (but note the missing root-level .dotfile):

$ tar -czvf ../ball.tar.gz *
[…]
$ tar -tzf ../ball.tar.gz
dir/
dir/.hidden
dir/file.txt
root.txt

If you don’t care about packing dot-files in the CWD, you’re done.

If you do care, you’re not without recourse. On many shells (e.g. bash) it may be possible to include dot-files in the shell glob by changing a shell option. With bash, this is done with shopt:

dotglob

If set, bash includes filenames beginning with a '.' in the results of pathname expansion.

$ shopt -s dotglob  # Include dot-files in pathname expansions
$ tar -czvf ../ball.tar.gz *
[…]
$ shopt -u dotglob  # Restore shell's default globbing behavior
$ tar -tzf ../ball.tar.gz
.dotfile
dir/
dir/.hidden
dir/file.txt
root.txt

GNU (Linux) Solution

Use --xform as mentioned in Jordan Bonitatis’s answer.

Usual behavior:

$ tar -czvf ../ball.tar.gz .
[…]
$ tar -tzf ../ball.tar.gz
./
./root.txt
./.dotfile
./dir/
./dir/file.txt
./dir/.hidden

No dot-slash:

$ tar -czvf ../ball.tar.gz --xform 's:^\./::' . [--show-transformed-names|--show-stored-names]
[…]
$ tar -tzf ../ball.tar.gz
./
root.txt
.dotfile
dir/
dir/file.txt
dir/.hidden

BSD (Mac OS X) Solution

Use -s, which is deceptively similar to pax/sed, but not quite, as shown below.

Usual behavior:

$ tar -czvf ../ball.tar.gz .
[…]
$ tar -tzf ../ball.tar.gz
./
./.dotfile
./dir/
./root.txt
./dir/.hidden
./dir/file.txt

No dot-slash:

$ tar -czvf ../ball.tar.gz -s '/.//' .
tar: Removing leading '/' from member names
[…]
$ tar -tzf ../ball.tar.gz 
.dotfile
dir/
root.txt
dir/.hidden
dir/file.txt
2

Not sure what version of tar this is, but normally you have to specify what files you want to archive. Like tar c . to compress everything in the local directory. Running your command on my machine I get:

tar: Cowardly refusing to create an empty archive

So, if you don't want to get the leading ./, which is what you get when you compress the local directory ., you can simply specify the files directly. For example:

> tar c hosts fstab | tar tv
-rw-r--r-- root/root      1225 2012-10-20 13:37 hosts
-rw-r--r-- root/root       678 2012-05-13 22:09 fstab
2

I use this:

tar --create --directory a_dir $(ls --almost-all a_dir) > archive.tar

This will list all files and directories (excent . and ..) of directory a_dir and add them to the archive. The --directory options sets the root from where tar will start looking for files.

1

I've used tar -P to preserve the leading / (rather than ./) It's not entirely clear if this would help in your case, though.

-P, --absolute-names
    don't strip leading '/'s from file names 

man tar

2
  • 'tar czf dist.tgz --exclude=".gitignore" .'
    – Aram
    Dec 17, 2012 at 9:36
  • What? Yes, throw a P in there and call it good. Dec 21, 2012 at 20:02
1

In the old versions of tar, it used to use the full path names you provided, in the tar, but this is somehow problematic as one might want a second copy of something and an unintentional expansion of the tar archive in the old format days, might overwrite an existing file or files.

So, in most recent versions of tar binary, distributed in almost any linux distribution, puts the ./ at the beginning of each file it packs up, so that, an unintentional expansion, expands the archive into your current working directory and below.

I am not sure why it is causing such a problem for you. if you are in the right directory level, where you want to expand this archive into, it will do just that. For instance, lets say you have a file as

/tmp/myarchive.tar

and let's assume the contents of the archive are

./etc/hosts
./etc/profile
./etc/passwd
./etc/group

if you expand this archive while your current working directory is / (i.e. root level), these files will go and overwrite the existing

/etc/hosts
/etc/profile
/etc/passwd
/etc/group

if this is what you want, you've got it. But let's say, you only wanted the hosts files out of this archive but all of a sudden you obliterated profile passwd and group files. Hope you have a good backup at this point, so that you can get them back

But, if you are the type of sysadmin, who avoids being in the root level, unless he/she needs it intentionally, you are most probably logged in ans located under /home/some-user or if you logged in as root, you are in /root directory. Let's say your in /root. when you execute the command

# tar -xvf /tmp/myarchive.tar

you will end up with

/root/etc/hosts
/root/etc/profile
/root/etc/passwd
/root/etc/group

no harm, no foul. Then

# mv /root/etc/hosts /etc/hosts

Voila. You accomplished your goal.

4
  • You can also use tar -C / to extract to root level without going there.
    – chutz
    Dec 12, 2012 at 16:40
  • Yes, I see that.. my example was to explain the risks of absolute vs. relative paths.
    – MelBurslan
    Dec 12, 2012 at 16:58
  • I tried all you wrote here. I don't need absolute paths. I need relative to folder I gave but without leading './'.
    – Aram
    Dec 17, 2012 at 9:37
  • ./ denotes a relative folder. SO you should have nothing to worry about
    – MelBurslan
    Dec 17, 2012 at 18:21

You must log in to answer this question.

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