ChatGPT解决这个技术问题 Extra ChatGPT

如何仅同步特定的文件列表?

我想推送到远程服务器的各个子目录中有大约 50 个左右的文件。我认为 rsync 可以使用 --include-from 选项为我执行此操作。没有 --exclude="*" 选项,目录中的所有文件都被同步,使用该选项,没有文件。

rsync -avP -e ssh --include-from=deploy/rsync_include.txt --exclude=* ./ root@0.0.0.0:/var/www/ --dry-run

我最初运行它是干的,0.0.0.0 显然被远程服务器的 IP 取代。 rsync_include.txt 的内容是我要上传的文件的相对路径的新行分隔列表。

有没有更好的方法让我在星期一早上逃脱?


J
Josip Rodin

有一个标志 --files-from 完全符合您的要求。从 man rsync

--files-from=FILE 使用此选项允许您指定要传输的文件的确切列表(从指定的 FILE 读取或 - 用于标准输入)。它还调整了 rsync 的默认行为,以使仅传输指定的文件和目录更容易:隐含 --relative (-R) 选项,它保留为文件中的每个项目指定的路径信息(使用 --no -relative 或 --no-R 如果你想关闭它)。 --dirs (-d) 选项是隐含的,它将创建在目标列表中指定的目录,而不是嘈杂地跳过它们(如果要关闭它,请使用 --no-dirs 或 --no-d )。 --archive (-a) 选项的行为并不意味着 --recursive (-r),因此如果需要,请明确指定它。这些副作用会改变 rsync 的默认状态,因此命令行中 --files-from 选项的位置与其他选项的解析方式无关(例如 -a 在 --files- 之前或之后的工作方式相同)来自,以及 --no-R 和所有其他选项)。从 FILE 读取的文件名都是相对于源目录的——任何前导斜杠都被删除,并且不允许“..”引用高于源目录。例如,使用以下命令: rsync -a --files-from=/tmp/foo /usr remote:/backup 如果 /tmp/foo 包含字符串“bin”(甚至是“/bin”),则 /usr/ bin 目录将在远程主机上创建为 /backup/bin。如果它包含“bin/”(注意尾部斜杠),也会发送目录的直接内容(无需在文件中明确提及——这始于版本 2.6.4)。在这两种情况下,如果启用了 -r 选项,也会传输该目录的整个层次结构(请记住,需要使用 --files-from 显式指定 -r,因为 -a 没有暗示它)。另请注意,(默认启用)--relative 选项的效果是仅复制从文件中读取的路径信息——它不会强制复制源规范路径(在这种情况下为 /usr) .此外,如果您在文件前面指定“host:”(主机必须匹配传输的一端),则可以从远程主机而不是本地主机读取 --files-from 文件。作为捷径,您可以只指定前缀“:”来表示“使用传输的远程端”。例如: rsync -a --files-from=:/path/file-list src:/ /tmp/copy 这将复制位于远程“src”上的 /path/file-list 文件中指定的所有文件“ 主持人。如果指定了 --iconv 和 --protect-args 选项并且 --files-from 文件名从一个主机发送到另一台主机,则文件名将从发送主机的字符集转换为接收主机的字符集。注意:对 --files-from 输入中的文件列表进行排序有助于 rsync 更有效,因为它将避免重新访问在相邻条目之间共享的路径元素。如果输入没有排序,一些路径元素(隐含的目录)可能最终会被扫描多次,并且 rsync 最终会在它们变成文件列表元素后取消重复。


请注意,您仍然必须指定列出的文件所在的目录,例如:rsync -av --files-from=file-list . target/ 用于从当前目录复制文件。
是的,重申一下:The filenames that are read from the FILE are all relative to the source dir
啊,错过了,对不起!
如果 files-from 文件有任何以 .. 开头的内容,rsync 似乎会忽略 ..,给我一个类似 rsync: link_stat "/home/michael/test/subdir/test.txt" failed: No such file or directory 的错误(在这种情况下,从“test”目录运行并尝试指定“../subdir/ test.txt" 确实存在。
是否可以将 --files-from 参数与包含和排除的显式列表结合使用,并且使用 --files-from 添加的列表中的文件是否会覆盖现有的排除规则,以便它们出现在文件中时被包含在内?
K
K F

根据记录,除了一个之外,上述答案都没有帮助。总而言之,您可以使用 --files-from= 执行备份操作,方法是:

rsync -aSvuc `cat rsync-src-files` /mnt/d/rsync_test/

或者

rsync -aSvuc --recursive --files-from=rsync-src-files . /mnt/d/rsync_test/

前一个命令是不言自明的,除了我将在下面详细说明的文件 rsync-src-files 的内容之外。现在,如果你想使用后一个版本,你需要记住以下四点:

请注意,需要同时指定 --files-from 和源目录 需要明确指定 --recursive。文件 rsync-src-files 是用户创建的文件,它被放置在 src 目录中以进行此测试。 rsyn-src-files 包含要复制的文件和文件夹,它们是相对于源目录获取的。重要提示:确保文件中没有尾随空格或空行。在下面的示例中,只有两行,而不是三行(偶然发现)。 rsynch-src-files 的内容是:

文件夹名称 1 文件夹名称 2


B
Brian Tompsett - 汤莱恩

如果要保持绝对路径不变,--files-from= 参数需要尾部斜杠。因此,您的命令将如下所示:

rsync -av --files-from=/path/to/file / /tmp/

这可以像有大量文件并且您想将所有文件复制到 x 路径一样完成。所以你会找到这些文件并将输出扔到一个文件中,如下所示:

find /var/* -name *.log > file

W
Wes Hardaker

编辑: atp 下面的答案更好。请使用那个!

如果您正在寻找特定的文件列表,您可能会更轻松,而是将它们直接放在命令行上:

# rsync -avP -e ssh `cat deploy/rsync_include.txt` root@0.0.0.0:/var/www/

然而,这是假设您的列表不会太长以至于命令行长度会成为问题,并且 rsync_include.txt 文件只包含真实路径(即没有注释,也没有正则表达式)。


不幸的是,这不适用于大型列表或名称中带有空格的文件。
[参数列表太长]
默认情况下,xargs 将参数从标准输入附加到命令行的末尾。这不起作用,因为 rsync 需要最后一个参数作为目标。某些版本的 xargs 可以选择在命令行中间插入参数。只要您不介意在文件列表很长时它可能会多次运行 rsync ,这应该可以工作。无论如何,rsync --files-from 可能是一个更简单、更可靠的解决方案 :)
Wes Hardaker:你的编辑 &引用“Josip Rodin 的答案”实际上是指罗丹编辑的 @atp answer
这个答案不应该是最佳答案,因为当我(可能还有更多人)创建一个脚本来复制数据时,我不喜欢有多个文件需要照顾,因为从长远来看这会使维护变得困难。最好将 --files-from 用于 onsies 或 twosies,并将 INCLUDE 和 EXCLUDE 用于较大的批次。
s
sopel

我有类似的任务:rsync 在给定日期之后修改的所有文件,但不包括某些目录。很难构建一个一体式的班轮风格,所以我将问题分解成更小的部分。最终解决方案:

find  ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS" | egrep -v "/\..|Downloads|FOO" > FileList.txt
rsync -v --files-from=FileList.txt ~/sourceDIR /Destination

首先我使用 find -L ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS"。我尝试将 regex 添加到 find 行以排除名称模式,但是我的 Linux (Mint) 风格无法理解 find 中的否定正则表达式。尝试了多种正则表达式 - 无法按需要工作。所以我最终得到 egrep -v - 排除模式简单方法的选项。我的 rsync 没有复制像 /.cache/.config 这样的目录以及我明确命名的其他目录。


我相信您可以使用流程替换将其变成bash单行:rsync -v --files-from=<(find ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS" | grep -Ev "/\..|Downloads|FOO") ~/sourceDIR /Destination
C
Chris

当我只有一个目录列表时,这些答案都不适合我。然后我偶然发现了解决方案!您必须将 -r 添加到 --files-from,因为 -a 在这种情况下不会递归(谁知道?!)。

rsync -aruRP --files-from=directory.list . ../new/location

如果您在文件中列出“dir”,那么您需要指定 -r/--recursive;如果你列出“dir/”你没有。
V
Victoria Stuart
$ date
  Wed 24 Apr 2019 09:54:53 AM PDT
$ rsync --version
  rsync  version 3.1.3  protocol version 31
  ...

语法:rsync <args> <file_and_or_folder_list> <source_dir> <destination_dir/>

文件夹名称 - 带有尾随 /;例如 Cancer - Evolution/ - 在文件中提供(例如 my_folder_list):

# comment: /mnt/Vancouver/my_folder_list
# comment: 2019-04-24
some_file
another_file
Cancer/
Cancer - Evolution/
Cancer - Genomic Variants/
Cancer - Metastasis (EMT Transition ...)/
Cancer Pathways, Networks/
Catabolism - Autophagy; Phagosomes; Mitophagy/

所以这些是“源”(文件和/或)文件夹,要进行 rsync'd。

请注意,如果您不包括上面显示的尾随 /rsync 会创建目标文件夹,但它们是空的。

<file_and_or_folder_list> 中提供的文件夹名称附加到其路径的其余部分:<src_dir> = /home/victoria/RESEARCH - NEWS(此处为不同分区),从而提供了 rsync 的完整文件夹路径;例如:... /home/victoria/RESEARCH - NEWS/Cancer - Evolution/ ...

[ 我稍后(2022-07)正在编辑这个答案,我不记得提供给 <src_dir> 的路径是 /home/victoria/RESEARCH - NEWS 还是 /home/victoria/RESEARCH - NEWS/ - 提供正确的连接路径。我相信是前者;如果它不起作用,请使用后者。]

请注意,您还需要使用 --files-from= ...,而不是 --include-from= ...

同样,rsync 语法是:

rsync <args> <file_and_or_folder_list> <source_dir> <destination_dir/>

所以,

rsync -aqP --delete --files-from=/mnt/Vancouver/my_folder_list "/home/victoria/RESEARCH - NEWS" $DEST_DIR/

在哪里

是 -aqP --delete

是 --files-from=/mnt/Vancouver/my_folder_list

是“/home/victoria/RESEARCH - NEWS”

是 $DEST_DIR/ (注意尾随 / 添加到变量名)

在我的 BASH 脚本中,为了编码灵活性,我将变量 $DEST_DIR 定义为如下两部分。

BASEDIR="/mnt/Vancouver"
DEST_DIR=$BASEDIR/data
echo $DEST_DIR                 ## /mnt/Vancouver/data

## To clarify, here is $DEST_DIR with / appended to the variable name:
echo $DEST_DIR/                ## /mnt/Vancouver/data/
echo $DEST_DIR/apple/banana    ## /mnt/Vancouver/data/apple/banana

但是,您可以更简单地指定目标路径:

通过 BASH 变量:$DEST_DIR=/mnt/Vancouver/data 注意在上面的 rsync 表达式中,/ 被附加到 $DEST_DIR(即 $DEST_DIR/ 实际上是 $DEST_DIR + /),给出目标目录路径 /mnt/Vancouver /数据/

请注意,在上面的 rsync 表达式中,/ 被附加到 $DEST_DIR(即 $DEST_DIR/ 实际上是 $DEST_DIR + /),给出目标目录路径 /mnt/Vancouver/data/

明确说明目标路径:/mnt/Vancouver/data/

使用的 rsync 选项: ## man rsyncrsync -h

 -a  :   archive: equals -rlptgoD (no -H,-A,-X)
    -r  :   recursive
    -l  :   copy symlinks as symlinks
    -p  :   preserve permissions
    -t  :   preserve modification times
    -g  :   preserve group
    -o  :   preserve owner (super-user only)
    -D  :   same as --devices --specials

  -P  :  same as --partial --progress

  -q  :   quiet (https://serverfault.com/questions/547106/run-totally-silent-rsync)

  --delete
    This  tells  rsync to delete extraneous files from the RECEIVING SIDE (ones
    that AREN’T ON THE SENDING SIDE), but only for the directories that are
    being synchronized.  You must have asked rsync to send the whole directory
    (e.g.  "dir" or "dir/") without using a wildcard for the directory’s contents
    (e.g. "dir/*") since the wildcard is expanded by the shell and rsync thus
    gets a request to transfer individual files, not the files’ parent directory.
    Files  that  are  excluded  from  the transfer are also excluded from being
    deleted unless you use the --delete-excluded option or mark the rules as
    only matching on the sending side (see the include/exclude modifiers in the
    FILTER RULES section).  ...

谢谢,这是这里最有帮助和解释性的答案
M
Matthias M

该答案不是该问题的直接答案。但它应该可以帮助您找出最适合您的问题的解决方案。

分析问题时,您应该激活调试选项 -vv

然后 rsync 将输出哪些文件被哪个模式包含或排除:

building file list ... 
[sender] hiding file FILE1 because of pattern FILE1*
[sender] showing file FILE2 because of pattern *