A Python script for automatically extracting an archive file in a subfolder:
#!/usr/bin/env python3
// sub7z.py
import subprocess
import re
import os, sys, pathlib
class Counter:
counter = 0
def getCount(self):
self.counter = self.counter + 1
return self.counter
class ZipFile:
pattern1 = re.compile(r" +Date +Time +Attr +Size +Compressed +Name\n-{4,}[- ]*\n(.*?)\n-{4,}[- ]*", re.DOTALL)
pattern2 = re.compile(r"\d{4}-\d{2}-\d{2} +\d{2}:\d{2}:\d{2} +\.+ +\d+ +\d+ +(.*?)\n")
def __init__(self, pFilePath):
self.filePath = os.path.abspath(pFilePath)
if not os.path.isfile(self.filePath):
raise Exception("You must give me a file as input!")
self.fileParent = os.path.dirname(self.filePath)
self.fileStem, self.fileExt = os.path.splitext(self.filePath)
self.zipItems = ""
self.withSubfolder = True
self.zipItemsFrom7z()
self.checkSubfolder()
def zipItemsFrom7z(self):
p = subprocess.Popen(["7z", "l", self.filePath], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
self.zipItems, err = p.communicate()
if err:
raise Exception("Failed to fetch zip file info through 7z.")
if not self.zipItems:
raise Exception("Didn't get any output from 7z, check that 7z is working properly.")
self.zipItems = self.zipItems.decode()
self.zipItems = self.pattern1.findall(self.zipItems)[0]
self.zipItems = self.pattern2.findall(self.zipItems)
def checkSubfolder(self):
dirnames = [pathlib.Path(i).parts[0] for i in self.zipItems]
if len(set(dirnames)) > 1:
self.withSubfolder = False
else:
self.subFolder = os.path.join(self.fileParent, dirnames[0])
def stripPathSep(self, folder):
while folder.endswith(os.sep):
folder = folder[:-1]
return folder
def makeNumberedFolder(self, folder):
folder = self.stripPathSep(folder)
newFolder = folder
counter = Counter()
while os.path.exists(newFolder):
print("This folder exists already: %s" % newFolder)
newFolder = folder + "%03d" % counter.getCount()
print("This folder name can be used without conflict: %s" % newFolder)
return newFolder
def makeFolderSameNameAsFileStem(self):
self.folderSameNameAsFileStem = self.makeNumberedFolder(self.fileStem)
os.mkdir(self.folderSameNameAsFileStem)
def setTargetFolder(self):
if self.withSubfolder:
subFolderName = os.path.split(self.subFolder)[1]
print("Archive contains a subfolder: %s." % subFolderName)
if os.path.exists(self.subFolder):
print("But this subfolder already exists. \nSo I cannot use this subfolder.")
print("I will figure out a usable folder name.")
self.inferFolderName = True
else:
print("And this subfolder does not exist yet.")
print("I will extract archive directly.")
self.inferFolderName = False
else:
print("Archive does not contain a subfolder.")
print("I will figure out a usable folder name.")
self.inferFolderName = True
if self.inferFolderName:
self.makeFolderSameNameAsFileStem()
self.targetFolder = self.folderSameNameAsFileStem
else:
self.targetFolder = self.fileParent
def extract(self):
self.setTargetFolder()
p = subprocess.Popen(["7z", "-o%s" % self.targetFolder, "x", self.filePath])
if __name__ == "__main__":
filePath = sys.argv[1]
if filePath.endswith(".tar.gz"):
secondPassFilePath = filePath[:-3]
unzipCmd = "gunzip"
elif filePath.endswith(".tgz"):
secondPassFilePath = filePath[:-2] + "ar"
unzipCmd = "gunzip"
elif filePath.endswith(".tar.bz2"):
secondPassFilePath = filePath[:-4]
unzipCmd = "bunzip2"
elif filePath.endswith(".tbz2"):
secondPassFilePath = filePath[:-3] + "ar"
unzipCmd = "bunzip2"
else:
unzipCmd = ""
if unzipCmd:
subprocess.call([unzipCmd, filePath])
filePath = secondPassFilePath
z = ZipFile(filePath)
z.extract()