emmdee
emmdee

Reputation: 1631

Rsync: Exclude directory contents, but include directory

I know that a directory can be excluded with --exclude like this:

rsync -avz --exclude=dir/to/skip /my/source/path /my/backup/path

This will omit the directory dir/to/skip

However I want to copy the directory itself but not the contents | Is there a one-liner with rsync to accomplish this?

Essentially, include dir/to/skip but exclude dir/to/skip/*

NOTE: I did search for this question. I found a lot of similar posts but not exactly this. Apologies if there is a dupe already.

Upvotes: 3

Views: 3274

Answers (2)

John1024
John1024

Reputation: 113994

Try:

rsync -avz --include=src/dir/to/skip --exclude=src/dir/to/skip/* src_dir dest_dir

--include=src/dir/to/skip includes the directory. --exclude=src/dir/to/skip/* excludes everything under the directory.

In general, a single rsync command can contain many such --include and --exclude filter rules. Their order is important: they are processed in the order they appear on the command line and the first matching rule is the one that is acted on. Subsequent rules are ignored.

Upvotes: 2

Mike Holt
Mike Holt

Reputation: 4612

The --exclude option takes a PATTERN, which means you just should just be able to do this:

rsync -avz --exclude='dir/to/skip/*' /my/source/path /my/backup/path

Note that the PATTERN is quoted to prevent the shell from doing glob expansion on it.

Since dir/to/skip doesn't match the pattern dir/to/skip/*, it will be included.

Here's an example to show that it works:

> mkdir -p a/{1,2,3}
> find a -type d -exec touch {}/file \;
> tree --charset ascii a
a
|-- 1
|   `-- file
|-- 2
|   `-- file
|-- 3
|   `-- file
`-- file

3 directories, 4 files


> rsync -r --exclude='/2/*' a/ b/
> tree --charset ascii b
b
|-- 1
|   `-- file
|-- 2
|-- 3
|   `-- file
`-- file

3 directories, 3 files

It is important to note that the leading / in the above PATTERN represents the root of the source directory, not the filesystem root. This is explained in the rsync man page. If you omit the leading slash, rsync will attempt to match the PATTERN from the end of each path. This could lead to excluding files unexpectedly. For example, suppose I have a directory a/3/2/ which contains a bunch of files that I do want to transfer. If I omit the leading / and do:

rsync -r --exclude='2/*' a/ b/

then the PATTERN will match both a/2/* and a/3/2/*, which is not what I wanted.

Upvotes: 4

Related Questions