Python Forum
Moving directories by filetype
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Moving directories by filetype
#1
Not homework, but a very elementary script, that has a seemingly complex problem.

It mostly works. It is used to move directories based on the filetype content. It should move the target filetype *AND* all other types in the dir and subdirs. It mostly works, except when it doesnt.

I can move an App dir with mixed file types 4-5 levels deep mostly without errors. But sometimes only parts of a directory are moved, and sometimes they are moved to dest while a .\dest\dest\sourcedir is created with other portions of the top level source dir.

I believe there is something simple and elementary I am missing here:


#!python38
import os
from fnmatch import fnmatch
import shutil

#zzmoveapps.py - Script to segregate Application dirs from other types (videos,pics,etexts) 

root = '.'
dest = '.\zApps'

for path, subdirs, files in os.walk(root):
    for name in files:
        if name.endswith(('.exe', '.zip', '.7z', '.msi','.rar')): 
           print(path)
           dest2 = os.path.join(dest, path)
           print(dest2)

           try:
               shutil.move(path,dest2)
               print("Directory '%s' created successfully" % dest2)
           except OSError as error:
               print("Directory '%s' can not be created" % dest2)
Reply
#2
The walk should be pruned to exclude the subdirs of the dirs moved and the destination directory
import os

def dirs_to_move(root, dest):
    for path, subdirs, files in os.walk(root):
        if path == dest:
            subdirs[:] = []
        elif any(name.endswith(('.exe', '.zip', '.7z', '.msi','.rar')) for name in files):
            yield path
            subdirs[:] = []

for d in dirs_to_move('.', '.\zApps'):
    print(d)
Reply
#3
(Feb-08-2022, 08:53 AM)Gribouillis Wrote: The walk should be pruned to exclude the subdirs of the dirs moved and the destination directory
import os

def dirs_to_move(root, dest):
    for path, subdirs, files in os.walk(root):
        if path == dest:
            subdirs[:] = []
        elif any(name.endswith(('.exe', '.zip', '.7z', '.msi','.rar')) for name in files):
            yield path
            subdirs[:] = []

for d in dirs_to_move('.', '.\zApps'):
    print(d)

Many thanks! But while this was a definite improvement, still a few bugs:

#!python38

import os
from fnmatch import fnmatch
import shutil

#zzmoveapps.py - Script to segregate Application dirs from other types (videos,pics,etexts) 

root = '.'
dest = '.\zApps'



def dirs_to_move(root, dest):
    for path, subdirs, files in os.walk(root):
        if path == dest:
            subdirs[:] = []
        elif any(name.endswith(('.exe', '.zip', '.7z', '.msi','.rar')) for name in files):
            yield path
            subdirs[:] = []
 
for d in dirs_to_move('.', '.\zApps'):
    print(d)
    shutil.move(d,dest)
No longer creates ./zApp/zApp dirs.
But occasionally will leave the directory at the root, (and sometimes the next level of non target files)and dump its target files contents into the ./zApp
destination dir.

A seeming problem with :
root\ MyShinyApp \ bunchadocs \ exefiles
-->
root\ MyShinyApp \ bunchadocs
root\ zApp \ exefiles

instead of the proper
root\zApp\MyShinyApp \ bunchadocs \ exefiles

Also is there any links to fully explain the subdirs[:] = [] syntax.
The colon is unfamiliar.
Reply
#4
An addendum to my last post .

I tried the revised script out with a couple of dozen etext dirs (modified the target extensions):
All worked well EXCEPT the one labelled something like
Contemporary Foo Texts - Collection 355 (Bar, Baz 43) # which contained about 30 etexts

All the etexts appeared in
root \ zBooks
BUT - the sirectory name itself disappeared.

However - If the directory was renamed literally 'foo' , containing all the original 30 texts:
it was moved perfectly to
root \ zBooks \ foo \ (30 etexts inside)

Could there be issues with the string structure?
Non alpha chars?
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020