zip folder's and take the name of folder - python

I'm trying to make this code which take the content of each folder in directory and add it to zip one by one with the name of folder
I did made this code but I'm blocked with just add file by extension in zip
import zipfile, os
handle = zipfile.ZipFile('ALL-PY.zip', 'w')
for x in os.listdir():
if x.endswith(directory):
handle.write(x,compress_type = zipfile.ZIP_DEFLATED)
handle.close()

I would follow this approach:
import zipfile, os
handle = zipfile.ZipFile('ALL-PY.zip', 'w')
path = "C:/Users/User_Name/my_directory" # This is YOUR INPUT - set with the directory you want to zip
os.chdir(path)
for directory, subs, files in os.walk("."):
handle.write(directory)
for this_file in files:
handle.write(os.path.join(directory, this_file), compress_type = zipfile.ZIP_DEFLATED)
handle.close()

Related

open a folder to then use the files in python correctly

Usually I navigate to the folder I am extracting data from and copy the file name directly:
df2=pd.read_csv('10_90_bnOH-MEA.csv',usecols=[1])
If I have multiple files and want to do the same for all the files, how do I specify the folder to open and get all the files inside?
I want to run the above code without specifying the file's full path
(C:\Users\X\Desktop\Y\Z\10_90_bnOH-MEA.csv)
You want listdir from the os module.
import os
path = "C:\\Users\\X\\Desktop\\Y\\Z\\"
files = os.listdir(path)
print(files)
dataframe_list = []
for filename in files:
dataframe_list.append(pd.read_csv(os.path.join(path,filename)))
You should open the desired directory and loop through all the files then do something to them.
# import required module
import os
# assign directory
directory = 'files'
# iterate over files in
def goThroughDirectory(directory):
for filename in os.listdir(directory):
f = os.path.join(directory, filename)
# checking if it is a file
if os.path.isfile(f):
# do something
If you also want to loop through all the files in a directory you should add a check for if os.path.isdir(f) like this
...
def goThroughDirectory(directory):
for filename in os.listdir(directory):
f = os.path.join(directory, filename)
# checking if it is a file
if os.path.isfile(f):
# do something
elif os.path.isdir(f):
# its not a file but a directory then loop through that directory aswell
goThroughDirectory(directory + "\" + f)
for more information you should check geeksforgeeks

Copy files with specific text at the end of their (file) names from one folder to other folder

I have 23000 files in one folder and want to copy files with their names ending with some specific text to other folder using python. I used the following code, though it runs successfully but it doesn't copy the file in the destination folder.
import os
import shutil
path = "D:/Snow_new/test"
outpath = "D:/Snow_new/testout"
for f in os.listdir(path):
if f.endswith("clip_2"):
shutil.copyfile(os.path.join(path, f), outpath)
you are trying to copy files to a single filename again and again, so to fix it you will have to add the filename with outpath for every file
import os
import shutil
path = "D:/Snow_new/test"
outpath = "D:/Snow_new/testout"
if not os.path.isdir(outpath):
os.mkdir(outpath)
else:
shutil.rmtree(outpath)
os.mkdir(outpath)
for f in os.listdir(path):
f2, ext = os.path.splitext(f)
if f2.endswith("clip_2"):
shutil.copyfile(os.path.join(path, f), os.path.join(outpath, f))
before running the above code make sure that you remove D:/Snow_new/testout completly

how to use zip.write() on directories using a relative path in python?

I am wanting to add explicit entries for the directories in my zipfile. For example my zipfile includes:
assets/images/logo.png
When in reality I need it to include:
assets/
assets/images/
assets/images/logo.png
So my question is, how do I add the directories as explicit entries using relative paths? I tried to use zip.write(relative/path/to/directory) but it says it can't find the directory, since its a relative path. It works when I put
/Users/i510118/Desktop/Engineering/kit-dev-portal-models/src/kit_devportal_models/static_data/static_extension/created_extnsn_version_update2/assets/images/logo.png
inside of zipfile.write(), but I need it to just be the relative path, which is just
assets/images/logo.png
is this possible?
Here is my full code
buf = io.BytesIO()
zipObj = zipfile.ZipFile(buf, "w")
extension_folder = "created_extnsn_version_update2"
with zipObj:
# Iterate over all the files in directory
for folderName, subfolders, filenames in os.walk(path_to_extension_directory):
# If the folder is not the root folder the extension is in
if not folderName.endswith(extension_folder):
folder = folderName.split(f"{extension_folder}/", 1)[1]
else:
folder = ''
for filename in filenames:
# create complete filepath of file in directory
filePath = os.path.relpath(os.path.join(folderName, filename), path_to_extension_directory)
with open(f"{folderName}/{filename}", 'rb') as file_data:
bytes_content = file_data.read()
# Add folder to zip if its not the root directory
if folder:
zipObj.write(folder)
# Add file to zip
zipObj.writestr(filePath, bytes_content)
# edit zip file to have all permissions
zf = zipfile.ZipFile(buf, mode='a')
info = zipfile.ZipInfo(f"{folderName}/{filename}")
info.external_attr = 0o777 << 16
zf.writestr(info, f"{folderName}/{filename}")
# Rewind the buffer's file pointer (may not be necessary)
buf.seek(0)
return buf.read()
Please let me know if you need more information!
From code stolen from add empty directory using zipfile?
import zipfile
zf = zipfile.ZipFile('test.zip', 'w')
folders = [
"assets/",
"assets/images/",
]
for n in folders:
zfi = zipfile.ZipInfo(n)
zf.writestr(zfi, '')
zf.write('logo.png', 'assets/images/logo.png')
zf.close()
zf = zipfile.ZipFile('test.zip', 'r')
for i in zf.infolist():
print(f"is_dir: {i.is_dir()}; filename: {i.filename}")
zf.close()

How to not include folders when zipping a file using ZipFile in python?

Is there a way to not generate folders during zip? When I extract the zip, it needs to show all the files directly without accessing a folder.
file_paths = utils.get_all_file_paths(path)
with ZipFile("{}/files.zip".format(path), "w") as zip:
for file in file_paths:
zip.write(file, os.path.basename(file))
I already tried arcname but it will still generate a folder which is files.
EDIT:
My code above will already remove the parent folder. Right now, when I extract the zip file, it will show a folder first with a name same as the zip name. What I want is to zip all the files and when I extract it, it will show all the files directly. Basically, no folders must show during extraction.
I hope following example will helpful to you
import os
import zipfile
TARGET_DIRECTORY = "../test"
ZIPFILE_NAME = "CompressedDir.zip"
def zip_dir(directory, zipname):
if os.path.exists(directory):
outZipFile = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED)
for dirpath, dirnames, filenames in os.walk(directory):
for filename in filenames:
filepath = os.path.join(dirpath, filename)
outZipFile.write(filepath)
outZipFile.close()
if __name__ == '__main__':
zip_dir(TARGET_DIRECTORY, ZIPFILE_NAME)

Extract files from zip without keeping the structure using python ZipFile?

I try to extract all files from .zip containing subfolders in one folder. I want all the files from subfolders extract in only one folder without keeping the original structure. At the moment, I extract all, move the files to a folder, then remove previous subfolders. The files with same names are overwrited.
Is it possible to do it before writing files?
Here is a structure for example:
my_zip/file1.txt
my_zip/dir1/file2.txt
my_zip/dir1/dir2/file3.txt
my_zip/dir3/file4.txt
At the end I whish this:
my_dir/file1.txt
my_dir/file2.txt
my_dir/file3.txt
my_dir/file4.txt
What can I add to this code ?
import zipfile
my_dir = "D:\\Download\\"
my_zip = "D:\\Download\\my_file.zip"
zip_file = zipfile.ZipFile(my_zip, 'r')
for files in zip_file.namelist():
zip_file.extract(files, my_dir)
zip_file.close()
if I rename files path from zip_file.namelist(), I have this error:
KeyError: "There is no item named 'file2.txt' in the archive"
This opens file handles of members of the zip archive, extracts the filename and copies it to a target file (that's how ZipFile.extract works, without taking care of subdirectories).
import os
import shutil
import zipfile
my_dir = r"D:\Download"
my_zip = r"D:\Download\my_file.zip"
with zipfile.ZipFile(my_zip) as zip_file:
for member in zip_file.namelist():
filename = os.path.basename(member)
# skip directories
if not filename:
continue
# copy file (taken from zipfile's extract)
source = zip_file.open(member)
target = open(os.path.join(my_dir, filename), "wb")
with source, target:
shutil.copyfileobj(source, target)
It is possible to iterate over the ZipFile.infolist(). On the returned ZipInfo objects you can then manipulate the filename to remove the directory part and finally extract it to a specified directory.
import zipfile
import os
my_dir = "D:\\Download\\"
my_zip = "D:\\Download\\my_file.zip"
with zipfile.ZipFile(my_zip) as zip:
for zip_info in zip.infolist():
if zip_info.filename[-1] == '/':
continue
zip_info.filename = os.path.basename(zip_info.filename)
zip.extract(zip_info, my_dir)
Just extract to bytes in memory,compute the filename, and write it there yourself,
instead of letting the library do it - -mostly, just use the "read()" instead of "extract()" method:
Python 3.6+ update(2020) - the same code from the original answer, but using pathlib.Path, which ease file-path manipulation and other operations (like "write_bytes")
from pathlib import Path
import zipfile
import os
my_dir = Path("D:\\Download\\")
my_zip = my_dir / "my_file.zip"
zip_file = zipfile.ZipFile(my_zip, 'r')
for files in zip_file.namelist():
data = zip_file.read(files, my_dir)
myfile_path = my_dir / Path(files.filename).name
myfile_path.write_bytes(data)
zip_file.close()
Original code in answer without pathlib:
import zipfile
import os
my_dir = "D:\\Download\\"
my_zip = "D:\\Download\\my_file.zip"
zip_file = zipfile.ZipFile(my_zip, 'r')
for files in zip_file.namelist():
data = zip_file.read(files, my_dir)
# I am almost shure zip represents directory separator
# char as "/" regardless of OS, but I don't have DOS or Windos here to test it
myfile_path = os.path.join(my_dir, files.split("/")[-1])
myfile = open(myfile_path, "wb")
myfile.write(data)
myfile.close()
zip_file.close()
A similar concept to the solution of Gerhard Götz, but adapted for extracting single files instead of the entire zip:
with ZipFile(zipPath, 'r') as zipObj:
zipInfo = zipObj.getinfo(path_in_zip))
zipInfo.filename = os.path.basename(destination)
zipObj.extract(zipInfo, os.path.dirname(os.path.realpath(destination)))
In case you are getting badZipFile error. you can unzip the archive using 7zip sub process. assuming you have installed the 7zip then use the following code.
import subprocess
my_dir = destFolder #destination folder
my_zip = destFolder + "/" + filename.zip #file you want to extract
ziploc = "C:/Program Files/7-Zip/7z.exe" #location where 7zip is installed
cmd = [ziploc, 'e',my_zip ,'-o'+ my_dir ,'*.txt' ,'-r' ]
#extracting only txt files and from all subdirectories
sp = subprocess.Popen(cmd, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)

Categories