Create Archive with tar Including Dotfiles but Excluding Subdirectories

tar

I want to backup all the 'dotfiles' (f.e. .zshrc) under my home directory with tar, but excluding the directory structure and all subdirectories.

I've tried it several times with different commands, but the best i achieved was an archive which included the hidden directories under $HOME as well.

#!/bin/zsh
BACKUPFILE=dotfile_backup.tar.gz
tar --create --file=$HOME/$BACKUPFILE --auto-compress --no-recursion --exclude=. --exclude=.. --exclude=*/ --directory=$HOME .*

I also thought about using find and piping the result to tar, but with no luck. Does somebody know how to achieve this – seemingly easy – task?

PS: Most of the time when I'm using tar to create an archive, i have to think about xkcd comic:

xkcd 1168 🙂

Best Answer

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.

Related Question