Bash - 将ls命令的输出导入到rsync命令中进行同步。

7

我正在尝试使用rsync备份包含特定单词的文件夹,使用lsgreprsync。然而rsync好像无法接受grep的输出作为输入。我尝试了以下方法:

$ ls -d $PWD/** | grep March | rsync -av 'dst'

这实际上并没有做任何事情,即使只使用ls -d $PWD/** | grep March也可以产生我想要移动的文件夹列表。
$ ls -d $PWD/** | grep March | xargs -0 | rsync -av 'dst'
$ ls -d $PWD/** | grep March | xargs -0 echo | rsync -av 'dst'
$ ls -d $PWD/** | grep March | xargs -0 rsync -av 'dst'

许多(包括dst,这里我用\转义空格)的文件夹名称中都包含空格,我认为这可能会引起问题,所以尝试使用xargs命令来帮助移动它们,但依然无法移动。
我已经尝试使用sudorsync-avu选项以及-r选项(即使-a选项已经包含了-r),并通常使用--dry-run选项进行测试,但也尝试过不加该选项的情况。我做错了什么?
是否可以像这样把输入内容传输给rsync
我使用的是OSX 10.13.3操作系统,GNU bash版本为3.2.57(1)。
谢谢。

@rkta 谢谢。有什么“替代方案”吗? - Morten
你没有向“xargs -0”提供以null结尾的数据...如果您想限制作为参数传递给“xargs”的文件数量,则需要添加“-n”选项... 如果“dst”是您的目标,则需要在其前面放置源,因此您需要在“xargs”上使用“-I”...(可能带有“-n1”)。 使用echoxargs是调试的最简单方法... - Gert van den Berg
3个回答

8
使用有问题的lsgrep,您想要的可能是:
ls -d "$PWD"/** | grep March | xargs -r -n1 -I'{}' rsync -av '{}' 'dst'

更好的方法是使用--include-from
一种选择是让bash模拟一个命名管道:
rsync -av0 --include-from=<(find . -path '*March*' -print0) "$PWD"/ /dst/

你也可以将查找结果作为管道输出,例如:
find . -path '*March*' -print0| rsync -av0 --include-from=- "$PWD"/ /dst/

-path 用于在文件名中查找“March”。(类似于 grep

(rsync 也可以通过一些参数来完成过滤,比如 --include--exclude 模式)

类似于下面的命令(未经测试)。参见这里

rsync -av --include="*/" --include="*March*" --exclude="*" "$PWD"/ /dst/ 

哇,谢谢你提供如此详尽的答案!解决了如何做以及回答原始问题的方法;从 ls 进行管道传输。 - Morten
注意:如果使用了 -a 选项,则 rsync 中的 -r 选项是不必要的,因为 -a 已经包含了 -r。但是,如果您使用 --files-from 而不是 --include-from,则应明确指定它(-ar)以获得递归行为,因为 --files-from 会从 -a 中删除它。 - Giuseppe
1
@Giuseppe,find 命令会返回所有文件名...(没有 -type 选项来限制只搜索目录/文件) (find 命令会递归搜索,rsync 不需要) - Gert van den Berg

3
我建议先创建包含/排除的文件列表,然后执行以下操作:
rsync -avz --include-from=list.txt source/ destination/

关于

rsync -avz --exclude-from=list.txt source/ destination/

创建列表时,您可以使用以下类似的内容:
grep -r March /path > list.txt

谢谢您的回答!我考虑尝试将 ls -d $PWD/** | grep March 的输出写入文件,然后按照您的建议进行操作。这可能会是我要做的方法。虽然我认为如果可以像我尝试过的那样做某些事情,那么它的开销会更小,更符合我的直觉。顺便说一句,感谢您让我注意到 -z 选项,您几乎总是使用它吗?还是仅用于大文件? - Morten
@Morten -z 更多是一种习惯,但如果您想获得更快的速度并获得一些想法(实际上它们会禁用压缩),请查看此链接:https://gist.github.com/KartikTalwar/4393116 - nbari
为什么不使用ls(https://unix.stackexchange.com/questions/128985/why-not-parse-ls)?grep更可靠。 - kyodev

2
我想到了一个解决办法。使用find替换lsgrep,并直接将其输送到rsync。最终代码如下:
$ find . -type d -maxdepth 1 -name '*March*' -print0 | rsync -av0r --files-from=- ./ /dst/

这里的-print0-0会像Gert van den Berg所描述的那样“以null结尾”数据(因为有空格,所以我必须这样说)。-r似乎是多余的,因为它已经包含在-a中了,但是当使用--files-from时,必须为rsync指定-r才能进行递归同步。
非常感谢你们,真的很感激。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接