我试图在执行 rsync 备份之前计算它的大小:
du -hs -- $(rsync -avn --exclude --delete $source $target | grep / | grep -v " bytes/sec" | grep -v "deleting " | cut -d "/" -f2- | awk 'NF' | awk '$0="$source/"$0')
它失败并出现错误:参数列表太长。 据我了解,该命令大于 ARG_MAX 限制。
我也尝试过 xargs,但也失败了:
rsync -avn --exclude --delete $source $target | grep / | grep -v " bytes/sec" | grep -v "deleting " | cut -d "/" -f2- | awk 'NF' | awk '$0="$source/"$0'| xargs -P4 -n9999999 du -hs -- 2>/dev/null | tail -1 | awk {'print $1'}
(最终输出23GB,但远不止于此)
我的问题是:是否有另一种方法来预先计算 rsync 备份的大小?
谢谢
xargs
“失败”的原因是你丢弃了它的一些输出。
回顾一下,当你得到“参数列表太长”时,这意味着你的参数比内核常量大
ARG_MAX
xargs
通过多次运行相同的命令来解决这个问题。例如,如果 echo one two three four
太长,并且您将其与 xargs
分开,那么您将有效地运行
echo one two
echo three four
您会注意到,虽然原始输出是一行,但此重新表述会产生两行。使用
xargs
时,您需要认识到这样的事情。
回到您的示例,您需要接受
du
将运行多次,并采取额外的步骤将它们重新收集在一起。您已经在使用 Awk;所以只需编写一个更好的 Awk 脚本即可。
rsync -avn --exclude --delete "$source" "$target" |
awk -v s="$source" ' /bytes\/sec|deleting/ { next }
/\// { sub(/^[^/]*\//, s "/", $0) print } ' |
xargs -P4 du -ks -- 2>/dev/null |
awk '{ sum =+ $1 }
END { print sum / 1024*1024*1024 }'
还请注意,我们不想使用
du -h
,因为这样我们就无法预测它将使用什么输出单位。 xargs
最终可能会在最后一次调用中在单个小文件上运行它,然后您将获得以字节、千字节或兆字节为单位的输出,而不是使用 du -h
时的千兆字节输出。我们用 Awk 计算总数,然后然后以千兆字节为单位进行格式化。
(你可以想象一下,而不是硬编码千兆字节,但我将把它作为练习。)
我还将您复杂的
grep | cut / | awk
重构为一个 Awk 脚本,尽管无法访问数据,但很难确定它是否正确。我相信我修复了一个错误,您可能想在输出中添加 shell 变量 source
的值,而不是静态文本 $source
。请记住,shell 和 Awk 是两种不同的语言,并且无法访问彼此的变量。
最后,引用你的变量,并且当你显然不知道可以挤入多少个参数时,不要在
-n
中硬编码一个大的 xargs
值;无论如何,它都会默认为最大可能的数字。