python:tarfile相同的内容不同的输出

问题描述

考虑以下代码

import tarfile
from os import unlink
from pathlib import Path
from subprocess import Popen,PIPE
from time import sleep

dir0 = Path("/tmp/a")
dir0.mkdir(parents=True,exist_ok=True)
fil0 = dir0 / "eph0"
fil0.write_text("Text 0",encoding="UTF-8")
fil1 = dir0 / "eph1"
fil1.write_text("Text 1",encoding="UTF-8")
fil2 = dir0 / "eph2"
fil2.write_text("Text 2",encoding="UTF-8")


# Python
tgz = "/tmp/py.tgz"
with tarfile.open(tgz,"w:gz") as tar_obj:
    tar_obj.add("/tmp/a",arcname="a")
out = Popen(f"sha256sum {tgz}",shell=True,stdout=PIPE).stdout.read()
print(out)

sleep(5)
unlink(tgz)

tgz = "/tmp/py.tgz"
with tarfile.open(tgz,stdout=PIPE).stdout.read()
print(out)


# CMD - tar
tgz = "/tmp/tar_a0.tgz"
_ = Popen(f"tar czf {tgz} /tmp/a",stderr=PIPE,stdout=PIPE)
out = Popen(f"sha256sum {tgz}",stdout=PIPE).stdout.read()
print(out)

sleep(5)

tgz = "/tmp/tar_a1.tgz"
_ = Popen(f"tar czf {tgz} /tmp/a",stdout=PIPE).stdout.read()
print(out)


# CMD - gzip
tgz = "/tmp/gzp_a0.tgz"
_ = Popen(f"tar -c /tmp/a | gzip -n >{tgz}",stdout=PIPE).stdout.read()
print(out)

sleep(5)

tgz = "/tmp/gzp_a1.tgz"
_ = Popen(f"tar -c /tmp/a | gzip -n >{tgz}",stdout=PIPE).stdout.read()
print(out)

我正在创建一个文件夹、一些文件并使用 tarfile 模块和 tar 命令进行压缩。

输出为:

b'5b18528dde6c18897159b8e2d6d26e0ab95972f4206bbd01ad0deef2d64d8d6c  /tmp/py.tgz\n'
b'32b45721ea88a9c0d787d4f13687e606fdf14eea5aa9fdabb3860416f7fb6136  /tmp/py.tgz\n'
b'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855  /tmp/tar_a0.tgz\n'
b'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855  /tmp/tar_a1.tgz\n'
b'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855  /tmp/gzp_a0.tgz\n'
b'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855  /tmp/gzp_a1.tgz\n'

使用命令行我总是得到相同的文件,而不是使用 tarfile 模块,输出每次都不同。

有什么想法吗?

谢谢

解决方法

这种差异的主要原因是当您调用 var imgArray = New Array(); imgArray[0] = "example_A" imgArray[1] = "example_B" imgArray[2] = "example_C" imgArray[3] = "example_D" ... imgArray[n] = "example_n" var linkArray = New Array(); linkArray[0] = "example_A" linkArray[1] = "example_B" linkArray[2] = "example_C" linkArray[3] = "example_D" ... linkArray[n] = "example_n" function diceCast(){return Math.floor(Math.random()*n+1);}; function showImage(){ var imgNum = diceCast(); var objImg = document.getElementById("mainImg"); objImg.src = imgArray[imgNum]; objImg.onclick = ()=>window.open(linkArray[imgNum],'_blank'); } 时,您压缩内容,您只是将其存档。

相反,tar cf 模块,默认情况下,对档案内的内容进行 gunzip,并将内部压缩档案命名为与主档案相同的命名方式(所以这里是 a0.tgz 和 a1.tgz)。

并且“压缩内容”有两个不同的名称,因此加密哈希是不同的。

,

正如 VPfB 所指出的,问题是每次创建文件时 mtime 字段都不同,即使内容相同。

默认情况下,tar 命令会丢弃此信息。

相反,tarfile python 模块默认不这样做,但您可以使用 filter 参数进行设置:

import tarfile

def reset(tarinfo):
    tarinfo.uid = tarinfo.gid = 0
    tarinfo.uname = tarinfo.gname = "root"
    tarinfo.mtime = 1
    return tarinfo

with tarfile.open("/tmp/a.tar","w:xz") as tar_obj:
    tar_obj.add("/tmp/a",arcname="a",filter=reset)