我有一个不断增长的远程文件目录,我想在rsync
它们之前对其进行排序和过滤,目标是始终仅在我的目标目录中保留最新的 N 个文件(即或多或少的轮换方案)。由于rsync
似乎没有这方面的选项,我一直在使用“插入任意远程命令”的技术,如下所述:
https://stackoverflow.com/q/950062/787842
我想出了这个命令,我在目标主机上作为 cron 执行:
rsync -vrzO --delete \
-e ssh <remote_host>:'$(cd <remote_dir> && ls -t $PWD/* | head -n 25)' \
<destination_dir>
这在第一次时效果很好(即当目标目录为空时):仅复制 25 个最新文件。但是,当窗口“向前滑动”时(即,当新文件的到达应该在本地将旧文件推出时),问题是该--delete
选项无法按我的预期工作。我的猜测是,由于过滤掉的远程文件仍然存在(即它们只是被插入的'$(..)'
命令暂时隐藏),所以rsync
根本无法在本地过滤掉它们。我的理解是否正确,还有更好的方法吗?
答案1
您可以将您的命令模拟为,
rsync -vrzO --delete -e ssh <remote_host>:'<remote_dir>/file1 <remote_dir>/file2' <destination_dir>/
即替换 的输出cd <remote_dir> && ls -t $PWD/* | head -n 2
。
rsync--delete
适用于目录和您的命令替换正在提供文件列表。所以--delete
不工作。
摘自man rsync
:
- 删除
这告诉 rsync 从接收端删除无关的文件(不在发送端的文件),但仅适用于目录 正在同步。你 必须要求 rsync 发送整个目录(例如“dir”或“dir/”)而不使用目录内容的通配符(例如“dir/*”),因为通配符由shell扩展,rsync因此获得传输单个文件的请求,而不是文件的请求父目录。
答案2
将远程目录挂载到sshfs。然后你就可以把它当作本地目录了。
现在,要按修改时间对文件进行排序,最简单的方法是桀骜的全局限定符。目录中最近的 25 个文件是
*(NDom[1,25])
因此,如果您想先复制,请删除目的地的无关文件:
for x in source/*(NDom[1,25]); do
y=destination/${x:t}
if [[ ! -e $y || $x -nt $y ]]; then cp -p $x $y; fi
done
destination_files=(destination/*(NDom[1,25]))
if [[ ${#destination_files} -gt 25 ]]; then
shift $((${#destination_files} - 25)) destination_files
rm $destination_files
fi
这是在复制之前删除文件的另一种方法。当要复制新文件并且目的地已经有完整的补充文件时,此文件会删除最旧的文件。
destination_files=(destination/*(ND)); destination_count=$#destination_files
for x in source/*(NDom[1,25]); do
y=destination/${x:t}
if [[ $destination_count -gt 25 && ! -e $y ]]; then rm destination/*(NDom[-1]); fi
if [[ ! -e $y || $x -nt $y ]]; then cp -p $x $y; fi
done
(警告:上面的代码是直接在浏览器中输入的,我没有测试。)