使用 python zipfile 归档符号链接

Posted

技术标签:

【中文标题】使用 python zipfile 归档符号链接【英文标题】:archiving symlinks with python zipfile 【发布时间】:2016-03-03 21:00:59 【问题描述】:

我有一个脚本,可以创建包含符号链接的目录的 zip 文件。一世 惊讶地发现 zipfile 压缩了 链接而不是链接本身,这是我想要的 预期的。有人知道如何获取 zipfile 来压缩链接吗?

【问题讨论】:

【参考方案1】:

可以让 zipfile 存储符号链接,而不是文件本身。例如,请参阅here。脚本的相关部分是将符号链接属性存储在 zipinfo 中:

zipInfo = zipfile.ZipInfo(archiveRoot)
zipInfo.create_system = 3
# long type of hex val of '0xA1ED0000L',
# say, symlink attr magic...
zipInfo.external_attr = 2716663808L
zipOut.writestr(zipInfo, os.readlink(fullPath))

【讨论】:

python3 不区分 long 和 int,所以 zipInfo.external_attr = 0xA1ED0000L 应该可以工作(这更易读?) 我看到了更好的实现:zipInfo.external_attr |= 0xA0000000 魔法常数也都可用,例如stat.S_IFLINK【参考方案2】:

zipfile 似乎不支持存储符号链接。将它们存储在 ZIP 中的方式实际上不是 and is only available as a custom extension in some implementations 格式的一部分。特别是,Info-ZIP 的实现支持它们,因此您可以delegate to it instead。确保你的解压软件可以处理这样的档案——正如我所说,这个功能不是标准化的。

【讨论】:

谢谢。我最终分叉了一个子进程以使用带有--symlinks 的命令行 zip。它比 python zipfile lib 慢得多,但它确实支持符号链接。 @LarryMartell Info-ZIP 有一个共享库和一个独立的可执行文件,可以为您节省一些周期。我找不到任何文档。【参考方案3】:

我在 Zip 支持类中定义了以下方法

def add_symlink(self, link, target, permissions=0o777):
    self.log('Adding a symlink:  => '.format(link, target))
    permissions |= 0xA000

    zi = zipfile.ZipInfo(link)
    zi.create_system = 3
    zi.external_attr = permissions << 16
    self.zip.writestr(zi, target)

【讨论】:

【参考方案4】:

请找到一个完整的 Python 代码作为工作示例,该代码使用指向 /proc/cpuinfo 的符号链接 cpuinfo.txt 创建一个 cpuinfo.zip 存档。

#!/usr/bin/python

import stat
import zipfile

def create_zip_with_symlink(output_zip_filename, link_source, link_target):
    zipInfo  = zipfile.ZipInfo(link_source)
    zipInfo.create_system = 3 # System which created ZIP archive, 3 = Unix; 0 = Windows
    unix_st_mode = stat.S_IFLNK | stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH
    zipInfo.external_attr = unix_st_mode << 16 # The Python zipfile module accepts the 16-bit "Mode" field (that stores st_mode field from struct stat, containing user/group/other permissions, setuid/setgid and symlink info, etc) of the ASi extra block for Unix as bits 16-31 of the external_attr
    zipOut = zipfile.ZipFile(output_zip_filename, 'w', compression=zipfile.ZIP_DEFLATED)
    zipOut.writestr(zipInfo, link_target)
    zipOut.close()

create_zip_with_symlink('cpuinfo.zip', 'cpuinfo.txt', '/proc/cpuinfo')

您可以进一步发出以下命令(例如,在 Ubuntu 下)以查看存档如何解压缩为有效的符号链接:

unzip cpuinfo.zip
ls -l cpuinfo.txt
cat cpuinfo.txt

【讨论】:

【参考方案5】:

虽然不是 POSIX 标准的一部分,但许多 zip 实现支持在条目上存储通用文件系统属性。 4字节值的高字节代表文件模式。

基本上你需要复制ZipInfo.from_file,但不要点击链接或截断模式:

st = os.lstat(path)
mtime = time.localtime(st.st_mtime)
info = zipfile.ZipInfo(name, mtime[0:6])
info.file_size = st.st_size
info.external_attr = st.st_mode << 16
out_zip.writestr(info, os.readlink(path))

【讨论】:

以上是关于使用 python zipfile 归档符号链接的主要内容,如果未能解决你的问题,请参考以下文章

使用 zipfile 归档每个文件的正确方法是啥?

归档有关符号链接的 iOS 项目时出错

在 Spark 中的 EMR 上使用 --py-files 从 .zip 文件(使用 zipfile 包在 python 中创建)导入模块时出现问题

python 简单备份文件脚本v2.0

归档时应用程序获取“架构 armv7 的未定义符号”,除非我不剥离库中的链接产品

PHP:创建一个包含符号链接和空目录的tar归档文件