Skip to content

Instantly share code, notes, and snippets.

@larryv
Last active January 31, 2016 00:57
Show Gist options
  • Save larryv/77308658f73249ffcf30 to your computer and use it in GitHub Desktop.
Save larryv/77308658f73249ffcf30 to your computer and use it in GitHub Desktop.
converting Unix paths into rsync include patterns
# Read a stream of newline-terminated paths from standard input and
# write the corresponding rsync include patterns to standard output.
#
# In the input, directory paths -- and ONLY directory paths -- must end
# with a slash. All paths are treated as literal strings.
#
# The pattern generation assumes that directories' contents are to be
# copied recursively. It also assumes that "rsync --recursive
# --delete-excluded" will use a final "*" pattern to exclude all
# non-included files. Thus, all ancestors require include patterns too,
# or the pre-order traversal will be interrupted. (See the
# "INCLUDE/EXCLUDE PATTERN RULES" section of the rsync(1) man page.)
generate_include_patterns() {
sed -n '
# TODO: Test whether rsync can deal with duplicate slashes. If
# so, get rid of this and update the tail-chopping substitution
# at the end.
# Deduplicate slashes.
\|///*|s||/|g
# Append "**" to directory paths to let "rsync --recursive" copy
# all descendants. But first, unconditionally escape wildcard
# characters and backslashes because this is the only point at
# which we can reliably distinguish our "**"-ended pattern from
# a literal path that happens to end with "**".
\|/$| {
h
s/[*?[\]/\\&/g
s/$/**/
b Print
}
# Print patterns for the input path and all ancestors. If the
# current pattern contains wildcard characters, escape them (and
# backslashes) first, maintaining an unescaped copy in the hold
# space. (See the "INCLUDE/EXCLUDE PATTERN RULES" section of the
# rsync(1) man page.)
:Nonempty
/./ {
h
/[*?[]/s/[*?[\]/\\&/g
:Print
p
g
s|/[^/]*$||
b Nonempty
}
' | sort -u
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment