Home > Mobile >  Preserving all the subdirectories when saving a file - Python
Preserving all the subdirectories when saving a file - Python

Time:01-06

I have a folder with various subdirectories and within those are files with different extensions such as .jpg, .png, etc. I would like to only extract the .jpg files and perform some work on them such as cropping, etc and then I want to save these new files (i.e. cropped ones) into the subdirectories that they came from. However, I don't want these new files saved into the same folder from which they came from. Instead, I want them saved into a different folder that contains all of the same subdirectories with the same names from which they came from. This new folder must only contain the new cropped files. I have included an illustration below to better explain my question. enter image description here

I have tried the following:

for imgs in glob.iglob(self.Main_Folder   '//**/*.jpg', recursive=True):
    Output_Folder = os.path.join(os.path.dirname(imgs), "cropped"   str(idx)   ".jpg")

However, this overwrites the .jpg files located in their subdirectories in the Main Folder (i.e. it overwrites 1.jpg, 2.jpg, etc). Any help on this would be much appreciated!

CodePudding user response:

One thing to realize is that the paths that glob.iglob generates include the entire matched pattern, which includes your self.Main_Folder. So, you must first determine the sub-path relative to the main folder, and join that with the output folder. E.g. "main_folder/found/path.jpg" -> "found/path.jpg" -> "output_folder/found/path.jpg". The pathlib library provides an easy way to do that with Path.relative_to.

import glob
import os
import pathlib

main_folder = "somewhere/Main Folder"
output_folder = "somewhere/Output Folder"
for name in glob.iglob(os.path.join(main_folder, "**/*")):
    path = pathlib.Path(name)
    sub_path = path.relative_to(main_folder)
    output_path = os.path.join(output_folder, sub_path)
    print(output_path)

You can get fancier by using more of the pathlib API (especially the ability to join paths with /), but whether this is more clear is probably debatable:

main_folder = "somewhere/Main Folder"
output_folder = "somewhere/Output Folder"
for name in glob.iglob(str(main_folder / "**/*")):
    path = pathlib.Path(name)
    output_path = output_folder / path.relative_to(main_folder)
    print(output_path)

In Python 3.10, which as of this writing is the newest Python version, this can be simpler:

main_folder = pathlib.Path("scratch")
output_folder = pathlib.Path("output")
for name in glob.iglob("**/*", root_dir=main_folder):
    output_path = output_folder / name
    print(output_path)

CodePudding user response:

Basically, these are 3 issues

  • iglob for finding jpg files
  • Pillow for image manipulation
  • a mechanism for creating path to new jpg file

First you got already, second is trivial, third like this:

from pathlib import Path
apath = Path(“a/b/c/a.jpg”)  # to your jpg
root = “a/b”
new_dir = Path(“some/path”)
new_path = new_dir.joinpath(apath.relative_to(root))
# should be some/path/c/a.jpg

No python here, so not tested.

  •  Tags:  
  • Related