通过ls管道输出给rsync失败:含指定关键词文件夹备份问题
解决rsync无法接收grep输出作为输入的问题
嘿,我来帮你搞定这个rsync同步的问题!你遇到的核心问题是rsync默认不会从标准输入(管道)读取要同步的文件/文件夹列表,而且你的命令写法也有几个小问题,我一步步给你拆解和修正。
为什么你的原有命令失效?
你之前的命令 ls -d $PWD/** | grep March | rsync -av 'dst' 有两个关键问题:
- rsync的语法搞反了:你把
dst放在了源的位置,rsync的正确格式是rsync [选项] 源 目标,这里你没指定源,反而把目标当成了源,自然没效果。 - rsync默认不读取管道输入:要让它从stdin获取源列表,必须用
--files-from=-参数(-表示从标准输入读取)。
另外你用xargs -0的尝试也不对,因为ls的输出是换行分隔的,而-0是告诉xargs用null字符作为分隔符,两者不匹配,反而会把所有内容当成一个参数,导致同步失败。
正确的解决方案
方案1:用rsync的--files-from=-直接读取管道列表
这是最直接的方法,让rsync从stdin获取要同步的文件夹路径:
# 先确保bash开启了globstar(支持**递归匹配) shopt -s globstar ls -d "$PWD"/** | grep March | rsync -av --files-from=- . dst/
--files-from=-:告诉rsync从标准输入读取要同步的路径列表.:因为你的列表是绝对路径,这里用.作为源基准(rsync需要一个源目录参考,绝对路径的话这个参数不影响,但必须写)dst/:目标文件夹,末尾加/表示把源文件夹的内容同步到dst目录下;如果不加/,会在dst下创建和源同名的文件夹再同步内容。
方案2:用xargs逐个同步文件夹
如果你的文件夹名称包含空格、特殊字符,用xargs配合-I {}更安全,它会把管道的每一行作为单独的参数:
shopt -s globstar ls -d "$PWD"/** | grep March | xargs -I {} rsync -av {} dst/
-I {}:将管道输入的每一行替换为{},然后执行后面的rsync命令,每个文件夹单独同步。
更安全的替代:用find命令替代ls+grep
解析ls的输出其实有风险——如果文件夹名包含空格、换行或特殊字符,ls的输出会被拆分,导致错误。更靠谱的方式是用find直接筛选目标文件夹:
# 方法1:配合rsync的--files-from find "$PWD" -type d -name "*March*" | rsync -av --files-from=- . dst/ # 方法2:配合xargs的null分隔(完美处理特殊字符) find "$PWD" -type d -name "*March*" -print0 | xargs -0 -I {} rsync -av {} dst/
-type d:只匹配文件夹-name "*March*":筛选名称包含March的文件夹-print0:用null字符分隔输出,配合xargs -0可以完美处理包含空格、换行的文件名。
关键注意事项
- 确保开启
globstar:如果用**递归匹配子文件夹,需要先执行shopt -s globstar(bash默认可能没开启) - 目标路径的结尾
/:决定了同步的方式,加/是把源内容放到目标文件夹里,不加是在目标下创建源同名文件夹再同步 - 避免解析ls输出:特殊字符会导致各种奇怪的问题,优先用
find命令。
内容的提问来源于stack exchange,提问作者Morten
相关产品推荐
相关产品推荐

