2

I want to get all files in a directory (I reached it after doing several for loops - hence fourth.path) that ends with .npy or with csv and then zip those files. My code is running putting one file only in the zip file. What am I doing wrong? I tried to change my indents, but no zip file is being created

import json
import os
import zipfile
import zlib

directory = os.path.join(os.getcwd(), 'recs')
radarfolder = 'RadarIfxAvian'
file = os.listdir(directory)

def r(p, name):
    p = os.path.join(p, name)
    return p.replace("/", "\\") 

#This code will list all json files in e    ach file
for first in os.scandir(directory):
    if first.is_dir():
        for second in os.scandir(first.path):
            if second.is_dir():
               for third in os.scandir(second.path):
                if third.is_dir():
                    radar_folder_name = ''
                    list_files = ()
                    for fourth in os.scandir(third.path):
                        if fourth.is_dir():
                            if radarfolder in fourth.path:
                                radar_folder_name = fourth.path
                                print(radar_folder_name)
                                list_files = ()
                                for file in os.listdir(fourth.path):
                                    if file.endswith(".npy") | file.endswith(".csv"):
                                        list_files = (file)
                                        print(list_files)
                                    with zipfile.ZipFile(radar_folder_name +'\\' +'radar.zip', 'w', compression=zipfile.ZIP_DEFLATED ) as zipMe:
                                        zipMe.write(radar_folder_name +'\\' +list_files)            
                                        zipMe.close()

I tried to change my indents either resulting in error: TypeError: can only concatenate str (not "tuple") to str or no zip file being created

  • `list_files = (file)` is the same as `list_files = file`, so you only zip the latest file found! You want to replace this with `list_files.append(file)`, after initiating `list_files = []` ; then for the zipping at the end of your function, loop over list_files: `for file in zip_files: ..... ` – Swifty Jan 30 '23 at 18:27
  • Hmm it seems I didn't read your code carefully enough; the actual problem is the 'w' argument in your zip writing, which makes the code OVERWRITE the contents; replace it with 'a' (for append) and it should work better! (That said, first listing all files as per my 1st comment, then zipping them all in a loop would not hurt). – Swifty Jan 30 '23 at 18:38

3 Answers3

1

As I said in my second comment, your problem comes from the 'w' argument in your zipping statement. It causes the zip to be overwritten every time it's opened, which you do for each file you zip in. You can fix this 2 ways (at least):

  • Replace 'w' with 'a'; this way the files will be appended to your zip (with the side effect that, if you do this several times, files will be added more than once).
  • Keep the 'w', but only open the zip once, having listed all the files you want to zip before. See my code below.

I've taken the liberty to rewrite the part of your code where you look for the 'RadarIfxAvian' folder, since embedded for are clumsy (and if your folder structure changes, they might not work), replacing it with a multi-purpose recursive function.

Note that the folder structure will be included in the .zip; if you want to zip only the files themselves, consider doing os.chdir(radar_folder_name) before zipping the files.

# This function recursively looks for the 'filename' file or folder
# under 'start_path' and returns the full path, or an empty string if not found.
def find_file(start_path, filename):
    if filename in os.listdir(start_path):
        return start_path + '/' + filename
    for file in os.scandir(start_path):
        if not file.is_dir():
            continue
        if (deep_path:=find_file(start_path + '/' + file.name, filename)):
            return deep_path
    return ''

directory = os.path.join(os.getcwd(), 'recs')
radarfolder = 'RadarIfxAvian'

radar_folder_name = find_file(directory, radarfolder)
print(radar_folder_name)
list_files = []
for file in os.listdir(radar_folder_name):
    if file.endswith(".npy") or file.endswith(".csv"):
        list_files.append(file)
with zipfile.ZipFile(radar_folder_name + '/' + 'radar.zip', 'w', compression=zipfile.ZIP_DEFLATED ) as zipMe:
    for file in list_files:
        zipMe.write(radar_folder_name + '/' + file)

    
Swifty
  • 2,630
  • 2
  • 3
  • 21
1

If I understand your code correctly, you are looking for a folder "RadarIfxAvian" and want to place a .ZIP in that folder containing any .CSV or .NPY files in that directory. This should do the equivalent, using os.walk for the recursive search:

import os
import zipfile

for path, dirs, files in os.walk('recs'):
    if os.path.basename(path) == 'RadarIfxAvian':
        print(path)
        with zipfile.ZipFile(os.path.join(path, 'radar.zip'), 'w', zipfile.ZIP_DEFLATED) as zip:
            for file in files:
               if file.endswith(".npy") | file.endswith(".csv"):
                   print(file)
                   zip.write(file)
        break  # stop search once the directory is found and processed
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
0

I adjusted my code with the following steps:

  1. Put the if in a function
  2. writing the the zip by looping over each item in the list I appended
import json
import os
import glob
import zipfile
import zlib

directory = os.path.join(os.getcwd(), 'recs')
radarfolder = 'RadarIfxAvian'
file = os.listdir(directory)
list_files = []

def r(p, name):
    p = os.path.join(p, name)
    return p.replace("/", "\\") 

def tozip(path, file):
    filestozip = []
    if file.endswith(".npy") or file.endswith(".csv"):
        filestozip = (path + '\\' + file)
        list_files.append(filestozip)
    return list_files


#This code will list all json files in each file
for first in os.scandir(directory):
    if first.is_dir():
        for second in os.scandir(first.path):
            if second.is_dir():
               for third in os.scandir(second.path):
                if third.is_dir():
                    radar_folder_name = ''
                    filestozip = []
                    list_files.clear()
                    for fourth in os.scandir(third.path):
                        if fourth.is_dir():
                            if radarfolder in fourth.path:
                                radar_folder_name = fourth.path
                                for file in os.listdir(fourth.path):
                                    filestozip = tozip(radar_folder_name,file)
                                print(filestozip)
                                ZipFile = zipfile.ZipFile(r(radar_folder_name,"radar.zip"), "w")
                                for a in filestozip:
                                    ZipFile.write(a, compress_type= zipfile.ZIP_DEFLATED)
                                    print(radar_folder_name + "added to zip")