mnt-excl 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. #!/usr/bin/perl
  2. # This script takes a command-line arg of a source directory
  3. # that will be passed to rsync, and generates a set of excludes
  4. # that will exclude all mount points from the list. This is
  5. # useful if you have "bind" mounts since the --one-file-system
  6. # option won't notice the transition to a different spot on
  7. # the same disk. For example:
  8. #
  9. # mnt-excl /dir | rsync --exclude-from=- ... /dir /dest/
  10. # mnt-excl /dir/ | rsync --exclude-from=- ... /dir/ /dest/
  11. # ssh host mnt-excl /dir | rsync --exclude-from=- ... host:/dir /dest/
  12. #
  13. # Imagine that /dir/foo is a mount point: the first invocation of
  14. # mnt-excl would have output /dir/foo, while the second would have
  15. # output /foo (which are the properly anchored excludes).
  16. #
  17. # NOTE: This script expects /proc/mounts to exist, but could be
  18. # easily adapted to read /etc/mtab or similar.
  19. #
  20. # ADDENDUM: The addition of the --filter option (which has support for
  21. # absolute-anchored excludes) can make this screen unneeded in some
  22. # scenarios. If you don't need delete protection on the receiving side
  23. # (or if the destination path is identical to the source path), then you
  24. # can exclude some absolute paths from the transfer based on the mount
  25. # dirs. For instance:
  26. #
  27. # awk '{print $2}' /proc/mounts | grep -v '^/$' | \
  28. # rsync -avf 'merge,/- -' /dir host:/dest/
  29. use strict;
  30. use warnings;
  31. use Cwd 'abs_path';
  32. my $file = '/proc/mounts';
  33. my $dir = shift || '/';
  34. my $trailing_slash = $dir =~ m{./$} ? '/' : '';
  35. $dir = abs_path($dir) . $trailing_slash;
  36. $dir =~ s{([^/]*)$}{};
  37. my $trailing = $1;
  38. $trailing = '' if $trailing eq '.' || !-d "$dir$trailing";
  39. $trailing .= '/' if $trailing ne '';
  40. open(IN, $file) or die "Unable to open $file: $!\n";
  41. while (<IN>) {
  42. $_ = (split)[1];
  43. next unless s{^\Q$dir$trailing\E}{}o && $_ ne '';
  44. print "- /$trailing$_\n";
  45. }
  46. close IN;