creating archive using tar including all 'dotfiles' but excluding all subdirectories and /wo directory structure

You can use this command to backup all your dotfiles (.<something>) in your $HOME directory:

$ cd ~
$ find . -maxdepth 1 -type f -name ".*" -exec tar zcvf dotfiles.tar.gz {} +

regex using just tar?

method #1

I researched this quite a bit and came up empty. The limiting factor would be that when tar is performing it's excludes, the trailing slash (/) that shows up with directories is not part of the equation when tar is performing its pattern match.

Here's an example:

$ tar -v --create --file=do.tar.gz --auto-compress --no-recursion --exclude={'.','..','.*/'} .*
.qalculate/
.qt/
.qterm/
.qtoctave/
.RapidSVN
.RData
.Rhistory

This variant includes an exclude of .*/ and you can see with the verbose switch turned on to tar, -v, that these directories are passing through that exclude.

method #2

I thought maybe the switches --no-wildcards-match-slash or --wildcards-match-slash would relax the greediness of the .*/ but this had no effect either.

Taking the slash out of the exclude, .* wasn't an option either since that would tell tar to exclude all the dotfiles and dotdirectories:

$ tar -v --create --file=do.tar.gz --auto-compress --no-recursion --exclude={'.','..','.*'} .*
$

method #3 (Ugly!)

So the only other alternative I can conceive is to provide a list of files to tar. Something like this:

$ tar -v --create --file=do.tar.gz --auto-compress --no-recursion --wildcards-match-slash --exclude={'.','..','.*/'} $(ls -aF | grep -E "^\..*[^/]$")
.RapidSVN
.RData
.Rhistory

This approach has issues if the number of files exceeds the maximum amount of space for passing arguments to a command would be one glaring issue. The other is that it's ugly and overly complex.

so what did we learn?

There doesn't appear to be a straight-forward and elegant way to acomplish this using tar & regular expressions. So as to @terdon's comment, find ... | tar ... is really the more appropriate way to do this.


This kind of control over matching files is way outside tar's comfort zone. Its rules for matching files are limited to simple matches over names.

find is one way, but since you have zsh, you have it easier:

tar -cf "$HOME/$BACKUPFILE" --auto-compress .*(.)

That . in parentheses at the end of the wildcard expression is a glob qualifier that says “only match regular files”.

Symbolic links to regular files are not matched. If you change to .*(-.), they will be included, but the file won't end up in the archive unless it's also included. If you want to replace symbolic link by their targets, make that .*(-.:A) — :A adds the history expansion modifier that resolves all symbolic links to a path that doesn't use symbolic links.


This answer is based on slm's, but I will also show you how to include directories beginning with .

To zip up dot files in your home directory:

$ cd
$ find . -maxdepth 1 -type f -name ".?*" -exec tar czfv dotfiles.tgz {} +

To include directories:

$ find . -maxdepth 1 -name ".?*" -exec tar czfv dotfiles.tgz {} +

The ? is optional in the first command, but not in the second, otherwise, find will include the . (current) directory.

Tags:

Tar