BACKGROUND
I have some directory in my home directory called delivery_content. Inside that directory there are two folders content_123 and content_456. Each directory contains a text file. So the over all structure looks like the following.
-delivery_content
-content_123/
-content_123.txt
-content_456/
-content_456.txt
I am writing code that when given a directory it will zip all of it's contents.
CODE
import os
import shutil
from pathlib import Path
from datetime import datetime
DOWNLOAD_DIR = Path(os.getenv("HOME")) / "delivery_content"
date = datetime.today().strftime("%Y-%m-%d")
delivery_name = f"foo_{date}"
shutil.make_archive(str(DOWNLOAD_DIR / delivery_name), "zip", str(DOWNLOAD_DIR))
print("Zipping Has Complete")
So for the given code above i expect to see a foo_todays_date.zip in the DOWNLOAD_DIR and when i unzip it i expect to see the following
-content_123/
-content_123.txt
-content_456/
-content_456.txt
However I see the following
Is there a way i can avoid having a .zip inside my zipfile?
The problem is that you are putting the zip file inside the directory that you are archiving. make_archive is probably creating an empty file to verify it can write to the destination before it starts archiving. So it then sees the empty zip file as a file to archive. The only way I see around this using the make_archive function is to put the archive file outside of the directory to archive like below:
shutil.make_archive(str(DOWNLOAD_DIR / ".."/ delivery_name), "zip", str(DOWNLOAD_DIR))
You can always move the zip file into the DOWNLOAD_DIR afterward.
Related
What I have is an initial directory with a file inside D:\BBS\file.x and multiple .txt files in the work directory D:\
What I am trying to do is to copy the folder BBS with its content and incrementing it's name by number, then copy/move each existing .txt file to the newly created directory to make it \BBS1, \BBS2, ..., BBSn (depends on number of the txt).
Visual example of the Before and After:
Initial view of the \WorkFolder
Desired view of the \WorkFolder
Right now I have reached only creating of a new directory and moving txt in it but all at once, not as I would like to. Here's my code:
from pathlib import Path
from shutil import copy
import shutil
import os
wkDir = Path.cwd()
src = wkDir.joinpath('BBS')
count = 0
for content in src.iterdir():
addname = src.name.split('_')[0]
out_folder = wkDir.joinpath(f'!{addname}')
out_folder.mkdir(exist_ok=True)
out_path = out_folder.joinpath(content.name)
copy(content, out_path)
files = os.listdir(wkDir)
for f in files:
if f.endswith(".txt"):
shutil.move(f, out_folder)
I kindly request for assistance with incrementing and copying files one by one to the newly created directory for each as mentioned.
Not much skills with python in general. Python3 OS Windows
Thanks in advance
Now, I understand what you want to accomplish. I think you can do it quite easily by only iterating over the text files and for each one you copy the BBS folder. After that you move the file you are currently at. In order to get the folder_num, you may be able to just access the file name's characters at the particular indexes (e.g. f[4:6]) if the name is always of the pattern TextXX.txt. If the prefix "Text" may vary, it is more stable to use regular expressions like in the following sample.
Also, the function shutil.copytree copies a directory with its children.
import re
import shutil
from pathlib import Path
wkDir = Path.cwd()
src = wkDir.joinpath('BBS')
for f in os.listdir(wkDir):
if f.endswith(".txt"):
folder_num = re.findall(r"\d+", f)[0]
target = wkDir.joinpath(f"{src.name}{folder_num}")
# copy BBS
shutil.copytree(src, target)
# move .txt file
shutil.move(f, target)
Folder Structure:
rootfoder:
subfoler1:
image.jpg
subfoler2:
image.png
text.txt
subfoler3
I have to copy all the files/folder inside root folder to des folder.
But .jpg and .png file should be not copied and empty folder should also be copied.
Can this be done in python using any lib?
Use shutil for this:
import shutil
shutil.copytree('/tmp/source', '/tmp/target' , ignore=shutil.ignore_patterns('*.jpg', '*.png'))
shutil provides an ignore_patterns function to skip certain files on tree copying.
HTH,
ferdy
I'd like to add a 'honorable mention', even if I second ferdy on using shutil:
from dirsync import sync
sync("./Frog", "./Throat", action="sync", ignore=[".*py",".*jpg"], create=True)
from https://github.com/tkhyn/dirsync
It seems to have been written as a command line utility alternative to rsync and adds the option to storing a config file, but it is callable from python and does the job.
I am currently using extratall function in python to unzip, after unziping it also creates a folder like: myfile.zip -> myfile/myfile.zip , how do i get rid of myfile flder and just unzip it to the current folder without the folder, is it possible ?
I use the standard module zipfile. There is the method extract which provides what I think you want. This method has the optional argument path to either extract the content to the current working directory or the the given path
import os, zipfile
os.chdir('path/of/my.zip')
with zipfile.ZipFile('my.zip') as Z :
for elem in Z.namelist() :
Z.extract(elem, 'path/where/extract/to')
If you omit the 'path/where/extract/to' the files from the ZIP-File will be extracted to the directory of the ZIP-File.
import shutil
# loop over everything in the zip
for name in myzip.namelist():
# open the entry so we can copy it
member = myzip.open(name)
with open(os.path.basename(name), 'wb') as outfile:
# copy it directly to the output directory,
# without creating the intermediate directory
shutil.copyfileobj(member, outfile)
i'm a total python noob but i want to learn it and integrate it to my workflow.
I have about 400 files containing 4 different parts in the filename separated by an underline:
-> Version_Date_ProjectName_ProjectNumber
As we allways look at the Projectnumber first, we arranged the contents of the filename for new projects to:
-> ProjectNumber_Version_ProjektName
My Problem now is, that i like to rename all the existing files to be rearranged to the new format while having them backed up in a subdirectory called "Archiv".
It just has to be a simple script that i put in the directory and every file in this directory will be copied as backup and changed to the new filename.
EDIT:
My first step was to create a subfolder within the source directory, and it worked somehow. But no i saw, that i just need to backup the files with a specific file extension.
import os, shutil
src_dir= os.curdir
dst_dir= os.path.join(os.curdir, "Archiv")
shutil.copytree(src_dir, dst_dir)
i tried to extend the code with the solutions from here but it doesn't work out. :/
import os
import shutil
import glob
src_path = "YOU_SOURCE_PATH"
dest_path = "YOUR DESTINATION PATH"
if not os.path.exists(dest_path):
os.makedirs(dest_path)
files = glob.iglob(os.path.join(src_dir, "*.pdf"))
for file in files:
if os.path.isfile(file):
shutil.copy2(file, dest_path)
I am quite new to python.Here i am trying to create zip file of "diveintomark-diveintopython3-793871b' directory.I changed the current working directory using os.chdir() function.The zip file is created but the problem is when i extract the zip file i get the the following directory
Users/laiba/Desktop/diveintomark-diveintopython3-793871b
but i only want diveintomark-diveintopython3-793871b folder inside my zip folder not the whole nested directory created .Why is this happening and how i can solve this?
import zipfile, os
os.chdir('c:\\Users\\laiba\\Desktop')
myzip=zipfile.ZipFile('diveZip.zip','w',zipfile.ZIP_DEFLATED)
for folder,subfolder,file in os.walk('diveintomark-diveintopython3-793871b'):
myzip.write(folder)
for each in subfolder:
myzip.write(os.path.abspath(os.path.join(folder,each)))
for each in file:
myzip.write(os.path.abspath(os.path.join(folder,each)))
you could use argument arcname: name of the item in the archive as opposed to the full path name. But here you don't need it because you already are in the correct directory. Just drop the abspath and you're done (and also the duplicate folder entry)
import zipfile, os
os.chdir('c:\\Users\\laiba\\Desktop')
myzip=zipfile.ZipFile('diveZip.zip','w',zipfile.ZIP_DEFLATED)
for folder,subfolder,file in os.walk('diveintomark-diveintopython3-793871b'):
for each in subfolder+file:
myzip.write(os.path.join(folder,each))
myzip.close()
This is possible to do without changing directories but more complex, also more elegant since you don't have to chdir
import zipfile, os
root_dir = r"c:\Users\laiba\Desktop"
myzip=zipfile.ZipFile(os.path.join(root_dir,'diveZip.zip'),'w',zipfile.ZIP_DEFLATED)
for folder,subfolder,file in os.walk(os.path.join(root_dir,'diveintomark-diveintopython3-793871b')):
for each in subfolder+file:
source = os.path.join(folder,each)
# remove the absolute path to compose arcname
# also handles the remaining leading path separator with lstrip
arcname = source[len(root_dir):].lstrip(os.sep)
# write the file under a different name in the archive
myzip.write(source,arcname=arcname)
myzip.close()