Skip to content

Instantly share code, notes, and snippets.

@pmolodo
Created September 23, 2025 21:13
Show Gist options
  • Select an option

  • Save pmolodo/2938dfe7f4a76dc2d43cdc9496b720a4 to your computer and use it in GitHub Desktop.

Select an option

Save pmolodo/2938dfe7f4a76dc2d43cdc9496b720a4 to your computer and use it in GitHub Desktop.
BetterZipFile - python ZipFile subclass that handles symbolic links and permission bits when extracting
# better_zipfile by Paul Molodowitch is marked CC0 1.0.
# to view a copy of this mark, visit https://creativecommons.org/publicdomain/zero/1.0/
import sys
import zipfile
import stat
import os
if sys.platform == "win32":
BetterZipFile = zipfile.ZipFile
else:
class BetterZipFile(zipfile.ZipFile):
"""
ZipFile subclass that handles symbolic links and permission bits when extracting
"""
def _extract_member(self, member, targetpath, pwd):
if not isinstance(member, zipfile.ZipInfo):
member = self.getinfo(member)
# Check if this is a symbolic link
permission_bits = member.external_attr >> 16
if permission_bits != 0 and stat.S_ISLNK(permission_bits):
# Handle symbolic links
link_target = self.read(member).decode("utf-8")
symlink_path = os.path.join(targetpath, member.filename)
# Ensure parent directory exists
os.makedirs(os.path.dirname(symlink_path), exist_ok=True)
# Remove existing file/link if it exists
if os.path.lexists(symlink_path):
try:
os.unlink(symlink_path)
except Exception:
print(
f"Failed to remove existing file/link: {member.filename} at"
f" {symlink_path}"
)
raise
# Create the symbolic link
os.symlink(link_target, symlink_path)
return targetpath
# Handle regular files and directories
targetpath = super()._extract_member(member, targetpath, pwd)
if permission_bits != 0:
os.chmod(targetpath, permission_bits)
return targetpath
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment