ZipFile bad directory structure - python

I try make some scripts which helps me zip a file from selected dir.
I have:
import sys
import os
import zipfile
source_dir = "C:\\myDir\\yourDir\\"
zip = zipfile.ZipFile("C:\\myDir\\yourDirZip.zip","w",allowZip64=True)
for root, dirs, files in os.walk(source_dir):
for f in files:
zip.write(os.path.join(root,f))
zip.close()
After execution, in yourDirZip.zip is:
myDir/
yourDir/
...
I expect directly only yourDir or even only content of yourDir
Have you any ideas on how I can get what I want?

You can specify arcname parameter in the write method:
import sys
import os
import zipfile
source_dir = "C:\\myDir\\yourDir"
zip = zipfile.ZipFile("C:\\myDir\\yourDirZip.zip","w",allowZip64=True)
for root, dirs, files in os.walk(source_dir):
for f in files:
zip.write(os.path.join(root,f), arcname=f)
zip.close()

Related

How to run the code and write the file in the hidden folder

Hello I have a code to zip all folders it still works normally outside but when the path
'C:\Users\Dr Corn\AppData\Local\Temp'
It does not work again
Here is my code:
from posixpath import dirort
import zipfile
import os
path = r'C:\Users\Dr Corn\AppData\Local\Temp'
folders = os.listdir(path)
for folder in folders:
if os.path.isdir(folder):
print(folder)
with zipfile.zipfile(folder + '.zip', 'w', zipfile.zip_deflated) as newzip:
for dirpath, dires, files in os.walk(folder):
for files in files:
newzip.write(os.path.join(dirpath, file))
We look forward to your help, thank you for reading
The code shared in question has lot of case related issues as noted by #AvleMonke.
If attempt in code is to create a zip file for each directory in the path given then following is the modified version of code in question that works.
from posixpath import *
import zipfile
import os
path = r'C:\Test\Dr Corn\App Data\Local\Temp'
folders = os.listdir (path)
for folder in folders:
folder_full_path = path+'\\'+folder
if os.path.isdir (folder_full_path):
with zipfile.ZipFile (folder_full_path + '.zip', 'w', zipfile.ZIP_DEFLATED) as newzip:
for dirpath, dires, files in os.walk (folder_full_path):
for files in files:
newzip.write (os.path.join (dirpath, files))

Create a zip of folders using zipfile

I have a folder called my_folder at the following Path /Users/my_user_name/Desktop/my_folder. The folder my_folder contains more folders like 323456, 987654 etc. Those folders contain some content. I want to create a zip of all those folders called myzip.zip such that when someone unzips it they see all those folders like 323456, 987654 at the root.
My Code
import os
from pathlib import Path
from zipfile import ZipFile
DOWNLOAD_DIR = Path("/Users/my_user_name/Desktop/my_folder")
ZIPPED_FILE_DIR = Path("/Users/my_user_name/Desktop/my_zip")
def get_list_of_all_folders(download_dir: Path):
return [f for f in download_dir.iterdir() if download_dir.is_dir()]
def zip_files():
folder_list = get_list_of_all_folders(DOWNLOAD_DIR)
with ZipFile(ZIPPED_FILE_DIR / "my_zip.zip", "w") as zip:
# writing each file one by one
for folder in folder_list:
zip.write(folder)
zip_files()
I have a function called get_list_of_all_folders where it goes to my_folder and gets a list of all the folders inside it that we want to zip. Then I use that folder_list to zip up each folder as part of my final zip called my_zip.zip. However there is something really wrong with my code and I am not sure what? The my_zip.zip is only 35 kb small when I know for a fact I am zipping up content over 2 gigabytes.
I looked at the zipfile document but did not find much help here as there are not many examples.
ZipFile.write expects to be supplied with the name of a file to write to the zip, not a folder.
You will need to iterate over the files in each folder and call write for each one. For example:
from pathlib import Path
from zipfile import ZipFile
DOWNLOAD_DIR = Path("/Users/my_user_name/Desktop/my_folder")
ZIPPED_FILE_DIR = Path("/Users/my_user_name/Desktop/my_zip")
def scan_dir(zip, dir, base_dir):
for f in dir.iterdir():
if f.is_dir():
scan_dir(zip, f, base_dir)
else:
# First param is the path to the file, second param is
# the path to use in the zip and when extracted. I just
# trim base_dir off the front.
zip.write(f, str(f)[len(str(base_dir)):])
def zip_files():
with ZipFile(ZIPPED_FILE_DIR / "my_zip.zip", "w") as zip:
for f in DOWNLOAD_DIR.iterdir():
scan_dir(zip, f, DOWNLOAD_DIR)
zip_files()
There's probably a neater way to trim off the base directory, but this was done quickly :)
You can use: shutil.make_archive
Below example taken from: https://docs.python.org/3/library/shutil.html#archiving-example
>>> import os
>>> from shutil import make_archive
>>> archive_name = os.path.expanduser(os.path.join('~', 'myarchive'))
>>> root_dir = os.path.expanduser(os.path.join('~', '.ssh'))
>>> make_archive(archive_name, 'zip', root_dir)
'/Users/tarek/myarchive.zip'
EDIT:
Code using ZipFile library
import zipfile
import os
class ZipUtilities:
def toZip(self, file, filename):
zip_file = zipfile.ZipFile(filename, 'w')
if os.path.isfile(file):
zip_file.write(file)
else:
self.addFolderToZip(zip_file, file)
zip_file.close()
def addFolderToZip(self, zip_file, folder):
for file in os.listdir(folder):
full_path = os.path.join(folder, file)
if os.path.isfile(full_path):
print('File added: ' + str(full_path))
zip_file.write(full_path)
elif os.path.isdir(full_path):
print('Entering folder: ' + str(full_path))
self.addFolderToZip(zip_file, full_path)
if __name__ == '__main__':
utilities = ZipUtilities()
filename = 'newfile.zip'
directory = 'foldername'
utilities.toZip(directory, filename)

pathlib prints the current directory path

import os
import sys
import pathlib
for folderName,subfolders,filenames in os.walk('/'):
for filename in filenames:
# print(filename)
if filename.endswith('.pdf'):
path=pathlib.Path(filename).parent.absolute()
print("the file "+str(filename)+" has path "+str(path))
I want this script to look for all the pdf files in the os and i also want to print the path of the file but when i run the script it print the file names but prints the path in which i have the python script and not print the path to the pdf file.
This should work:
import os
import sys
import pathlib
for folderName,subfolders,filenames in os.walk('/'):
for filename in filenames:
if filename.endswith('.pdf'):
print(f"the file {filename} has path {folderName}")
You don't need pathlib for this one.
pathlib.Path(filename) will consider filename as a relative path, and thus its parent will be the folder from which the script was runned.

Extract all files from multiple folders with Python

I wrote down this code:
import shutil
files = os.listdir(path, path=None)
for d in os.listdir(path):
for f in files:
shutil.move(d+f, path)
I want every folder in a given directory (path) with files inside, the files contained in that folder are moved to the main directory(path) where the folder is contained.
For Example:
The files in this folder: C:/example/subfolder/
Will be moved in: C:/example/
(And the directory will be deleted.)
Sorry for my bad english :)
This should be what you are looking for, first we get all subfolders in our main folder. Then for each subfolder we get files contained inside and create our source path and destination path for shutil.move.
import os
import shutil
folder = r"<MAIN FOLDER>"
subfolders = [f.path for f in os.scandir(folder) if f.is_dir()]
for sub in subfolders:
for f in os.listdir(sub):
src = os.path.join(sub, f)
dst = os.path.join(folder, f)
shutil.move(src, dst)
Here another example , using a few lines with glob
import os
import shutil
import glob
inputs=glob.glob('D:\\my\\folder_with_sub\\*')
outputs='D:\\my\\folder_dest\\'
for f in inputs:
shutil.move(f, outputs)

Python: Copy files with specific extension in a tree of directory

I need to copy files with extension of .jpg from a folder tree.
The folder tree is like this:
-folder_A
-folder_1
-1.txt
-1.jpg
-folder_2
-2.txt
-2.jpg
-folder_3
-3.txt
-4.jpg
-folder_B
How can I copy all the x.jpg to folder_B?
i.e. All the files are the same in folder_A, and in folder_B, files are 1.jpg, 2.jpg...
Have a look at the python os module.
import os
import shutil as sh
root_path = "./folder_A"
dest_path = "./folder_B"
for dirpath, dnames, fnames in os.walk(root_path):
for f in fnames:
if f.endswith(".jpg"):
source_file_path = os.path.join(dirpath, f)
dest_file_path = os.path.join(dest_path, f)
sh.copyfile(source_file_path, dest_file_path)
Or if you know your OS you can just execute the according shell-command.
(But I think the solution of #stellasia is cleaner)
Example (Linux):
import os
os.system('cp -r folder_A/*/*.jpg folder_B/')

Categories