frickenate

System Administration

Rsync – deleting a remote directory

Emptying a Remote Directory with Rsync

The fairly common task of emptying a remote directory is quite straightforward with rsync:

rsync -vr --delete $(mktemp -d)/ user@example.com:/path/to/dir/

If we only have rsync daemon access, we have two options for the syntax:

rsync -vr --delete $(mktemp -d)/ user@example.com::/module/path/to/dir/
rsync -vr --delete $(mktemp -d)/ rsync://user@example.com/module/path/to/dir/

The use of mktemp -d is simply to avoid having to separately create an empty directory which we will sync to the remote server. It creates an empty directory in your system’s temporary directory, typically /tmp/.

Deleting a Remote Directory Entirely

What if we want to delete both the contents of a remote directory, as well as the directory itself? What we want is the rsync equivalent to the following command:

ssh user@example.com rm -rf /path/to/dir/

If we have ssh shell access to the server, the command to execute is listed right above. But what do we do in the case wherein we only have rsync access? It takes a close reading of the man page to determine the proper arguments, or – if you happen to be me – a trip to the #linux IRC channel on freenode.net. The first iteration of the command you might discover looks like this:

rsync -vr --delete --include '/dir/**' --include '/dir/' --exclude='*' $(mktemp -d)/ user@example.com::/module/path/to/

We first specify that we wish to delete all contents of the directory (--incude '/dir/**'), along with the directory itself (--include '/dir/'), whilst not affecting other subdirectories within /path/to/ (via --exclude '*'). Note that we must refer to the parent directory of the subdirectory we intend to delete as the root remote sync location. If we want to delete the remote /path/to/dir/ directory, we sync against its /path/to/ directory while specifying that we wish to include the dir/ subdirectory and its contents in the deletion, while excluding all other paths.

The Proper Command

A thorough reading of the rsync(1) man page reveals the following note:

INCLUDE/EXCLUDE PATTERN RULES

  • a trailing “dir_name/***” will match both the directory (as if “dir_name/” had been specified) and everything in the directory (as if “dir_name/**” had been specified). This behavior was added in version 2.6.7.

This means we can simplify having to specify both the contents of a remote directory as well as the directory itself down to a single --include filter:

rsync -vr --delete --include '/dir/***' --exclude='*' $(mktemp -d)/ user@example.com::/module/path/to/

The three asterisks, as indicated by the man page quote above, means we will sync both the directory itself and its contents in one filter. As we are syncing an empty directory, this will result in the directory being removed entirely, just as if we has executed an rm -rf /path/to/dir/.