mnt-excl 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. #!/usr/bin/perl -w
  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) has made this script less useful than it
  22. # was. Beginning with 2.6.4, you can achieve the effect of this script
  23. # through this command:
  24. #
  25. # awk '{print $2}' /proc/mounts | rsync -f 'merge,/- -' host:/dir /dest/
  26. use strict;
  27. use Cwd 'abs_path';
  28. my $file = '/proc/mounts';
  29. my $dir = shift || '/';
  30. $dir = abs_path($dir);
  31. $dir =~ s#([^/]*)$##;
  32. my $trailing = $1;
  33. $trailing = '' if $trailing eq '.' || !-d "$dir$trailing";
  34. $trailing .= '/' if $trailing ne '';
  35. open(IN, $file) or die "Unable to open $file: $!\n";
  36. while (<IN>) {
  37. $_ = (split)[1];
  38. next unless s#^\Q$dir$trailing\E##o && $_ ne '';
  39. print "- /$trailing$_\n";
  40. }
  41. close IN;