rsync:使用过滤器排除顶级目录,但包含其一些子目录

rsync:使用过滤器排除顶级目录,但包含其一些子目录

我想备份我的/home目录同步。我读过 rsync 的手册页并决定使用过滤规则来完成此任务。

我想实现的目标: 排除目录中的所有文件和目录Repos,但保留所有pull_all.sh文件和目录output目录--- 无论它们位于Repos目录中的哪个位置。

到目前为止,我最终得到了以下过滤器列表,但这仅备份pull_all.sh文件而不output备份目录:

# Files prefixed with "+ " are included. Files prefixed with "- " are excluded.
#
# The order of included and excluded files matters! For instance, if a folder
# is excluded first, no subdirectory can be included anymore. Therefore,
# mention included files first. Then, mention excluded files.
#
# See section "FILTER RULES" of rsync manual for more details.


# Included Files

# TODO: This rules do not work properly!
+ output/***
+ pull_all.sh
- Repos/**

# Excluded Files

- .android
- .cache
...

我在脚本中使用过滤器列表run_rsync.sh

#!/bin/bash

date="$(date +%Y-%m-%d)"
hostname="$(hostname)"

# debug_mode="" # to disable debug mode
debug_mode="--list-only"

# Note: With trailing "/" at source directory, source directory is not created at destination.
rsync ${debug_mode} --archive --delete --human-readable --filter="merge ${hostname}.rsync.filters" --log-file=logfiles/$date-$hostname-home.log --verbose /home backup/

不幸的是,现有的 StackExchange 线程并没有解决我的问题:

这里出了什么问题?

[更新] 以下是主目录的外观以及要保留哪些文件以及要忽略哪些文件的示例:

user@hostname:~$ tree /home/ | head
/home/
└── user
    ├── Desktop                -> keep this
    │   ├── file1              -> keep this
    │   └── file2              -> keep this
    ├── Documents              -> keep this
    ├── Repos
    │   ├── pull_all.sh        -> keep this
        ├── subdir1
        │   ├── output         -> keep this
        ├── subdir2
            ├── another_subdir
                ├── output     -> keep this
        ├── subdir3            -> do not keep (because does not contain any "output")
        ├── file3              -> do not keep

答案1

稍微重申一下我对您的要求的解释,

  • 包含所有pull_all.sh文件,无论我们在哪里找到它们
  • 包括所有output目录及其内容无论我们在哪里找到它们
  • 排除Repos除我们已经说明的目录之外的目录
  • 包括其他一切

这可以指定如下

rsync --dry-run --prune-empty-dirs -av

    --include 'pull_all.sh'
    --include 'Repos/**/output/***'

    --include '*/'

    --exclude 'Repos/***'

    /home backup/

一些笔记

  • --include '*/'是必需的,以便rsync考虑向下进入Repos目录树(以查找pull_all.sh文件),否则最终--exclude语句将排除该文件。
  • 三种不同的用途*是不同的:
    • *匹配除/字符之外的任何内容
    • **匹配任何内容,包括/字符
    • dir/***是相当于指定dir/and 的快捷方式dir/**
  • --prune-empty-dirs标志停止rsync创建空目录,这尤其重要,因为我们需要处理Repos目录树以查找pull_all.sh项目output
  • --dry-run当您对结果满意时删除。

答案2

您可以使用“+”表示所需的子目录,使用“-”表示其余目录:

rsync -auv "${src}" "${dst}" \
--filter=+_"/parent-dir/to-sync-child-dir/" \
--filter=-_"/parent-dir/*"

相关内容