Bash 如何确保原始文件和gzip版本不相同

Bash 如何确保原始文件和gzip版本不相同,bash,gzip,Bash,Gzip,我的测试设备会生成大型文本文件,随着数据的添加,这些文件的大小会在几天内逐渐增大 但是文本文件每天都会被传输到PC机上进行备份,在那里它们甚至在完成增长之前就被压缩成gzip 这意味着我经常同时拥有file.txt和一个压缩表单file.txt.gz,其中未压缩的文件可能比压缩版本更新 我决定使用下面的bashscriptgzandrm: #!/usr/bin/bash # Given an uncompressed file, look in the same directory for

我的测试设备会生成大型文本文件,随着数据的添加,这些文件的大小会在几天内逐渐增大

但是文本文件每天都会被传输到PC机上进行备份,在那里它们甚至在完成增长之前就被压缩成
gzip

这意味着我经常同时拥有
file.txt
和一个压缩表单
file.txt.gz
,其中未压缩的文件可能比压缩版本更新

我决定使用下面的
bash
script
gzandrm

#!/usr/bin/bash

# Given an uncompressed file, look in the same directory for 
# a gzipped version of the file and delete the uncompressed 
# file if zdiff reveals they're identical. Otherwise, the 
# file can be compressed.

# eg:  find . -name '*.txt' -exec gzandrm {} \;

if [[ -e $1 && -e $1.gz ]] 
then

    # simple check: use zdiff and count the characters
    DIFFS=$(zdiff "$1" "$1.gz" | wc -c)

    if [[ $DIFFS -eq 0 ]] 
    then

        # difference is '0', delete the uncompressed file
        echo "'$1' already gzipped, so removed"
        rm "$1"

    else

        # difference is non-zero, check manually
        echo "'$1' and '$1.gz' are different"

    fi

else
    # go ahead and compress the file
    echo "'$1' not yet gzipped, doing it now"
    gzip "$1"
fi
这很有效,但是比较文件的修改日期更有意义,因为压缩时,
gzip
不会更改修改日期,因此具有相同日期的两个文件实际上是相同的文件,即使其中一个文件被压缩


如何修改脚本以按日期而不是按大小比较文件?

您可以使用
stat
%Y
%Z
格式字符串轻松比较文件的日期戳,以获取上次修改或更改的时间(以秒为单位)

if [ $(stat -c %Z $1) -eq ($stat -c %Z $1.gz) ]; then
    echo "Last changed time of $1 is the same as $1.gz"
fi

现在还不完全清楚目标是什么,但它似乎是简单的效率,所以我认为您应该做两个更改:1)按照您的建议检查修改时间,如果未压缩的文件不比压缩的文件更新,则不必比较内容;2)使用
zcmp
而不是
zdiff

首先使用#2,您的脚本将执行以下操作:

DIFFS=$(zdiff "$1" "$1.gz" | wc -c)
if [[ $DIFFS -eq 0 ]]
它将对可能较大的文件执行完全差异,计算差异输出中的字符数,并检查计数。但你真正想知道的是内容是否不同
cmp
更好,因为它会逐字节扫描,如果遇到差异,就会停止。它不需要花时间来格式化一个好的文本比较(您通常会忽略);它的退出状态告诉您结果
zcmp
不如原始
cmp
效率高,因为它需要先进行解压缩,但
zdiff
也有同样的问题

因此,您可以切换到
zcmp
(并删除子shell的使用,消除
wc
,不调用
[[/code>,并避免将可能较大的文本差异数据放入变量),只需将上述两行更改为:

if zcmp -s "$1"    # if $1 and $1.gz are the same
要更进一步并首先检查修改时间,您可以使用
-nt
(更新于)选项对
test
命令(也称为方括号)进行修改,将上面的行改写为:

if [ ! "$1" -nt "$1.gz" ] || zcmp -s "$1"
也就是说,如果未压缩的版本不比压缩的版本更新,或者它们的内容相同,那么$1已经被压缩,您可以将其删除。请注意,如果未压缩的文件不更新,
zcmp
将根本不会运行,从而节省一些周期

脚本的其余部分应按原样工作


一个警告:修改时间很容易改变。只要把压缩文件从一台机器移到另一台机器,就可以改变它的Mod时间,所以你必须考虑你自己的情况,知道MOTIME检查是否是一个有效的优化还是比它的价值更麻烦。再唱一次。为什么不压缩文本版本(如果存在的话),然后一直放弃原始版本而选择压缩版本呢?因为我不想假设文本版本总是更好。在极少数情况下,文本版本是一个新文件,而不是附加了文本的旧文件。如果是新文件,它不应该有一个新名称吗文件实际上变小了?文件名是固定的,因为它定义了内容。有时设备的操作员必须用相同的名称重复测试,有时删除文件以节省磁盘空间。这很有趣,但由于未压缩的文件可能是一个新的文件,日期较晚,我可能不得不结合大小和ti测试你的用例很古怪(为不同的数据集重用示例文件名?),但如果您将这些测试结合起来,请确保通过首先运行时间测试并仅检查大小(如果它们不同)来节省计算时间。关于先检查时间的好主意,但生产的现实意味着我们有时只需要重新开始生成具有相同文件名的数据。稍后的数据集将替换第一个文件集(错误)数据集。如果后一个数据集替换了前一个数据集,即使它更小,为什么还需要比较大小?如果未压缩的时间戳比压缩的时间戳新(在上面的测试中使用

-gt
)然后需要重新压缩。后面的数据集可能会开始变小,但会随着时间的推移而增长。但是,是的,新数据通常会达到旧数据的大小,并且可能会超过旧数据,如果它不是因为部分重新测试而停止(在这种情况下,我们需要保留旧数据和新数据)。我认为我应该认为我不能保证保存所有数据——一些旧数据可能会被删除。谢谢@Rob,这给了我很多尝试。我使用FTP传输文件,所以修改时间不会改变,并且它仍然是一个有效的比较。