linux中的zip非确定性结果
我有这个剧本:linux中的zip非确定性结果,linux,bash,shell,zip,Linux,Bash,Shell,Zip,我有这个剧本: #/bin/bash mkdir-pab echo hello>hello.txt echo world>world.txt zip-r-X-*.txt>a/helloworld.zip 睡眠3 触摸hello.txt zip-r-X-*.txt>b/helloworld.zip cat a/helloworld.zip | md5sum-czip文件格式包含此字段(请参阅) 这意味着,如果时间戳可能不同,那么对完整zip文件进行校验和的方法将永远不起作用 一种可能的方法是使用已
#/bin/bash
mkdir-pab
echo hello>hello.txt
echo world>world.txt
zip-r-X-*.txt>a/helloworld.zip
睡眠3
触摸hello.txt
zip-r-X-*.txt>b/helloworld.zip
cat a/helloworld.zip | md5sum-czip文件格式包含此字段(请参阅)
这意味着,如果时间戳可能不同,那么对完整zip文件进行校验和的方法将永远不起作用
一种可能的方法是使用已经存储在zip存档中的CRC来进行每一个操作
档案中的文件。此字段是未压缩内容的CRC
您可以使用解压的-lv
选项来获取CRC和文件名
$ unzip -lv z.zip
Archive: z.zip
Length Method Size Cmpr Date Time CRC-32 Name
-------- ------ ------- ---- ---------- ----- -------- ----
175 Defl:N 127 27% 2020-06-21 22:34 2268840f xxx
-------- ------- --- -------
175 127 27% 1 file
您可以对该输出运行md5sum
,但首先删除时间戳数据,如下所示
$ unzip -lv z.zip | grep '^ *[0-9]' | sed -e 's/% [0-9-]* [0-9:]*/ /'
175 Defl:N 127 27 2268840f xxx
175 127 27 1 file
以下是基于您的脚本的概念证明
mkdir -p a b
echo hello > hello.txt
echo world > world.txt
zip -r -X - *.txt > a/helloworld.zip
sleep 3
touch hello.txt
zip -r -X - *.txt > b/helloworld.zip
unzip -lv a/helloworld.zip | grep '^ *[0-9]' | sed -e 's/% [0-9-]* [0-9:]*/ /'| md5sum
unzip -lv b/helloworld.zip | grep '^ *[0-9]' | sed -e 's/% [0-9-]* [0-9:]*/ /'| md5sum
这就产生了这个输出
$ sh /tmp/test.sh
adding: hello.txt (stored 0%)
adding: world.txt (stored 0%)
adding: hello.txt (stored 0%)
adding: world.txt (stored 0%)
be1ee35bf864a4a9f2394cc26d2c3b32 -
be1ee35bf864a4a9f2394cc26d2c3b32 -
正如其他地方提到的,zip文件包含时间戳,不能忽略它们。但是,可以将它们全部强制为单个值,这在生成可复制构建时非常有用
通常,这是通过-o
和-X
标志完成的-o
将所有时间戳设置为存档中任何文件使用的最早时间,-X
防止保存额外的每个操作系统时间戳
如果您知道只创建比最旧的文件更新的文件,则不需要执行任何其他操作。否则,您需要触摸给定的文件以生成适当的时间戳。您使用的时间戳并不重要,只要是一致的。例如,如果您的文件存储在Git中,您可能希望使用最新提交的提交者时间戳,或者您可能更喜欢使用历元;没关系
这看起来是这样的:
#!/bin/bash
archive () {
local archive="$1"
shift
# Any suitable timestamp can be used here.
touch -d 1970-01-01T00:00:00Z "$@"
TZ=UTC zip -r -oX - "$@" > "$archive"
}
mkdir -p a b
echo hello > hello.txt
echo world > world.txt
archive a/helloworld.zip *.txt
sleep 3
touch hello.txt
archive b/helloworld.zip *.txt
cat a/helloworld.zip | sha256sum -c <( cat b/helloworld.zip | sha256sum -b )
#/bin/bash
存档(){
本地存档=“$1”
转移
#这里可以使用任何合适的时间戳。
触摸屏-d 1970-01-01T00:00:00Z“$@”
TZ=UTC zip-r-oX-“$@”>“$archive”
}
mkdir-pab
echo hello>hello.txt
echo world>world.txt
存档a/helloworld.zip*.txt
睡眠3
触摸hello.txt
存档b/helloworld.zip*.txt
cat a/helloworld.zip | sha256sum-c一个选项可以是用unzip-p
替换cat
。相关:@kaylum我尝试了你的建议,效果很好,即使它没有考虑文件名。我仍然不知道这是否是我的问题。@Socowi我需要使用linux提供的工具。对于我的用例,编写和使用python脚本是不可行的,如果您还需要文件名,那么就使用-c
而不是-p
$ sh /tmp/test.sh
adding: hello.txt (stored 0%)
adding: world.txt (stored 0%)
adding: hello.txt (stored 0%)
adding: world.txt (stored 0%)
be1ee35bf864a4a9f2394cc26d2c3b32 -
be1ee35bf864a4a9f2394cc26d2c3b32 -
#!/bin/bash
archive () {
local archive="$1"
shift
# Any suitable timestamp can be used here.
touch -d 1970-01-01T00:00:00Z "$@"
TZ=UTC zip -r -oX - "$@" > "$archive"
}
mkdir -p a b
echo hello > hello.txt
echo world > world.txt
archive a/helloworld.zip *.txt
sleep 3
touch hello.txt
archive b/helloworld.zip *.txt
cat a/helloworld.zip | sha256sum -c <( cat b/helloworld.zip | sha256sum -b )