[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Exclude patterns



Damn I love Unix. Tarsnap doesn't do exclude files. I REALLY want exclude files. I like having the excludes enumerated as close as possible to the actual files. And that --nodump thing leaves me completely cold. An invisible flag that affects how things work? I don't think so. I always think about how the thing will work without protest for - oh, say - three years. Then it will break and I will have to fix it, and I won't remember what I did. So I really want those exclude files. Out in the open, right next to the files being backed up.

Getting back to loving Unix: I wrote a quickie wrapper for tarsnap in Perl. It goes and gets the excludes file from the top directory of the tree being backed up, and creates a tarsnap
command line.  Here it is:
----------------- snip ------------------
#!/usr/bin/perl
use strict;
use warnings;
#***********************************************************
# etarsnap
#  a wrapper for tarsnap with advanced excludes.
#  creates a tarsnap command with excludes gleaned from
#  a file called "excludes" at the top of each directory tree.
# the exclude file consists of one exclude per line.
# each exclude is a file or directory.
# this program tacks the root onto the front of the exclude
#  the trouble like that is it makes it hard to do excludes in the
#  form of "*.o"
# ************************************************************
use Data::Dumper;
my $argc = @ARGV;                       # number of command line args
my $tarsnap_cmd = '/usr/local/bin/tarsnap';
my $topdir = $ARGV[ $argc-1 ]; # last tarsnap parm is the dir to back up
my $excludes_filename = $topdir . "/excludes";

if( -e $excludes_filename )
        {
        # yes, there is an exclude file.
        # generate the excludes
# each exclude consists of "--exclude " + the root dir + the bare exclude from the file
        # yes, Virginia, there is an excludefile
        open( my $excludefile, "<", $excludes_filename );
my @bare_excludes = <$excludefile>; #slurp!
        my $num_excludes = @bare_excludes;
        foreach my $bare_exclude ( @bare_excludes )
                {
chomp $bare_exclude; # remove trailing line feed $bare_exclude =~ s/^\s*//; # remove leading white space $bare_exclude =~ s/\s*$//; # remove trailing white space

                # Don't emit blank lines.  Don't emit comment lines
                my $doit=0;
                if( $bare_exclude !~ m/^\s*#/ )
                        {
                        # not a comment
                        $doit = 1 if $bare_exclude =~ m/\s*\w+/;
                        $doit = 1 if $bare_exclude =~ m/^\s*\*/;
chomp $bare_exclude; # remove trailing line feed $bare_exclude =~ s/^\s*//; # remove leading white space $bare_exclude =~ s/\s*$//; # remove trailing white space

                # Don't emit blank lines.  Don't emit comment lines
                my $doit=0;
                if( $bare_exclude !~ m/^\s*#/ )
                        {
                        # not a comment
                        $doit = 1 if $bare_exclude =~ m/\s*\w+/;
                        $doit = 1 if $bare_exclude =~ m/^\s*\*/;
                        }

                if( $doit )
                        {
                        # remove trailing comments
                        $bare_exclude =~ s/#.*$//;

                        # remove trailing white space
                        $bare_exclude =~s/\s*$//;

                        my $exclude_parm = '--exclude ';
                        if( $bare_exclude !~ m/^\*/ )
                                {
                                # it's not *.o, etc
                                $exclude_parm .= $topdir . '/';
                                }
                        $exclude_parm .= $bare_exclude;
                        unshift @ARGV, $exclude_parm;
                        }
                }
        }

# now tack on the rest of the input parms to the tarsnap line
foreach my $arg(@ARGV)
        {
        $tarsnap_cmd .= ' ' . $arg;
        }
$tarsnap_cmd .= "\n";
#print $tarsnap_cmd;
`$tarsnap_cmd`;

--------------------- endsnip ------------------------------
Fair warning: I am not an expert Perl programmer. This thing seems to work, but YMMV and if your computer blows up into coruscating sparks, it's not my fault. Anyway, I named it "etarsnap" ( e for excludes ). When I back up a tree, it looks for a file called "excludes" at the top of the tree. If there is such a file, it opens it, gets all the lines and formats them into --exclude arguments for tarsnap. It ignores lines that start with #. It also allows you to append # comments after the individual excludes. It gets the top directories off of the tarsnap invocation and tacks them in front of those excludes that are not in the form of *something. Say, *~ or *.o. It then calls tarsnap itself with all the specified parameters, plus the excludes.

So I have a file, /root/excludes, which consists of:
-------------- snip ---------------------
# tarsnap excludes.  Maybe works for rsync also?
*~                      # editor backup files
.cpan/sources           # cpan cruft
.cpan/Metadata          # more cpan cruft
.cpan/build             # when will the cpan madness end?
-------------- endsnip -----------------------------

I execute the command:
 ./etarsnap --dry-run -cvf root /root

which generates and executes the following command:

/usr/local/bin/tarsnap --exclude /root/.cpan/build --exclude /root/.cpan/Metadata --exclude /root/.cpan/sources --exclude *~ --dry-run -cvf root /root

                  - Jerry Kaidor ( jerry@tr2.com )