Getting rsync to delete old non-empty directories containing excluded files

For some older projects we’re still deploying code with rsync, its not perfect but it works. Temporary files are excluded using --exclude-from=exclude.txt, this is great until the parent folder of an excluded file needs to be deleted.

For example, say your file structure looks like this:
Rsync delete file structure

And you remove the data/cache directory completely:

$ rm -rf data/cache
$ rsync --exclude="*.tmp" --exclude="data/logs/*.log"

You’re going to get the error “cannot delete non-empty directory: data/cache” because data/cache/config.tmp has not been removed by rsync.

Unfortunately --delete-excluded won’t work because you don’t want to delete the log files and other .tmp files created on the destination.

Fortunately rsync has filters (which include/exclude are shorthand for anyway), with a mode called “perishable”. Perishable excludes behave exactly as required, files are excluded from sync, and aren’t deleted on the destination unless they are in a directory that no longer exists.

The syntax for excluding files becomes:
$ rsync --filter="-,p *.tmp" --filter="-,p data/logs/"

The “-” signifies the filter is to exclude matches. The “p” makes the exclude perishable.

If, like us, you were using --exclude-from for the patterns, you can with this syntax:
$ rsync --filter="merge,p- /home/ideal/scripts/push/excludes/lenta.txt"

This information is all available in the rsync docs under “FILTER RULES”, it just took me a while to figure out the right syntax. Hopefully these snippets help someone out.

ChartBlocks goes in to beta

A project I’ve been working on for some time now has hit public beta. It is called “ChartBlocks” and allows you to design and publish charts online in a number of formats, with analytics and sharing built right in.

This will be the first public embed of a chart from the platform:

If you’re looking to create vector charts, which you can download and publish, or share with the internet (through Facebook, twitter, an embed on your website) sign up for the beta here.

jQuery find next element in DOM by selector

If you need to find the next occurrence of an element within the DOM, but aren’t sure where it is (i.e. you can’t just use $.next) I wrote a jQuery plugin that will traverse through the DOM from the current element til it hits either the ‘body’ tag or a parent you specify.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(function( $ ){
    $.fn.nextElementInDom = function(selector, options) {
        var defaults = { stopAt : 'body' };
        options = $.extend(defaults, options);
 
        var parent = $(this).parent();
        var found = parent.find(selector);
 
        switch(true){
            case (found.length > 0):
                return found;
            case (parent.length === 0 || parent.is(options.stopAt)):
                return $([]);
            default:
                return parent.nextElementInDom(selector);
        }
    };
})( jQuery );

Download it here: jquery.nextElementInDom.js

And here is how you would use it:

1
var elementNeeded = $('.firstElement').nextElementInDom('.secondElement');

Where your HTML might look like this:

<html>
  <body>
    <div>
      <span class="firstElement">Our first element</span>
    </div>
 
    <ul>
      <li>
        <span class="secondElement">Second element is in a different place</span>
      </li>
    </ul>
  </body>
</html>