import os
import stat
import tarfile
import zipfile
import utils
log = utils.stream_logger()
def extract_file(archive_path, extract_to, create_folder=""):
if len(create_folder) != 0:
extract_to = os.path.join(extract_to, create_folder)
if archive_path.endswith(".zip"):
folder_name = extract_zip(archive_path, extract_to)
elif archive_path.endswith(".tar.gz"):
folder_name = extract_tar(archive_path, extract_to)
elif archive_path.endswith(".tar"):
folder_name = extract_tar(archive_path, extract_to)
else:
raise TypeError(f"Unsupported compression type for file {archive_path.split('/')[-1]}")
if len(create_folder) != 0:
return create_folder
return folder_name
def extract_zip(zipfile_path, extract_to):
"""解压ZIP文件到指定目录"""
zip_ref = zipfile.ZipFile(zipfile_path, "r")
zip_ref.extractall(extract_to)
for info in zip_ref.infolist():
extracted_path = os.path.join(extract_to, info.filename)
if not info.is_dir() and info.external_attr:
unix_permissions = (info.external_attr >> 16) & 0o777
os.chmod(extracted_path, unix_permissions)
for info in zip_ref.infolist():
file_path = os.path.join(extract_to, info.filename)
if _is_symlink(info):
link_target = zip_ref.read(info.filename).decode("utf-8").strip()
if os.path.lexists(file_path):
os.remove(file_path)
os.symlink(link_target, file_path)
log.info(f"File {zipfile_path.split('/')[-1]} extraction complete")
return zip_ref.infolist()[0].filename.split("/")[0]
def extract_tar(tarfile_path, extract_to):
"""解压ZIP文件到指定目录"""
tar_ref = tarfile.open(tarfile_path, "r:*")
tar_ref.extractall(extract_to)
log.info(f"File {tarfile_path.split('/')[-1]} extraction complete")
return tar_ref.getnames()[0]
def _is_symlink(info):
"""检查 ZIP 条目是否为符号链接"""
mode = (info.external_attr >> 16) & 0xFFFF
return stat.S_IFMT(mode) == stat.S_IFLNK
def archive_tar(tarfile_path: str, archive_path):
"""压缩指定文件夹到压缩文件"""
mod = "w"
if tarfile_path.endswith(".tar.gz"):
mod = "w:gz"
base_path = os.path.basename(os.path.abspath(archive_path))
tar_ref = tarfile.open(tarfile_path, mod)
tar_ref.add(archive_path, arcname=base_path)
tar_ref.close()