Issue
As a "clean up" after my script's main purpose is complete, a function is called to recursively look through each folder and remove all files that end in a pre-determined set of extensions.
I during my testing, I discovered that some files with a file extension in the list of ones to delete actually throw an error: [Errno 1] Operation not permitted: '/location/of/locked/file.png
. Looking at the file itself, it appears to be Locked (on mac).
- How would I go about removing the locked attribute (should it exist) from every file/folder using Python, then delete the file if it ends in the extension?
Preferably this can all be done in the same function below, as it takes a long time to traverse the input directory - handling each only once is the way to go. - How does this affect the script's integrity on Windows?
I have taken care of programming it in a way that makes it compatible between the OSs but (to my knowledge) the locked attribute does not exist on Windows the way it does on mac and could cause unknown side-effects.
REMOVE_FILETYPES = ('.png', '.jpg', '.jpeg', '.pdf')
def cleaner(currentPath):
if not os.path.isdir(currentPath):
if currentPath.endswith(REMOVE_FILETYPES) or os.path.basename(currentPath).startswith('.'):
try:
os.remove(currentPath)
print('REMOVED: \"{removed}\"'.format(removed = currentPath))
except BaseException as e:
print('ERROR: Could not remove: \"{failed}\"'.format(failed = str(e)))
finally:
return True
return False
if all([cleaner(os.path.join(currentPath, file)) for file in os.listdir(currentPath)]):
try:
os.rmdir(currentPath)
print('REMOVED: \"{removed}\"'.format(removed = currentPath))
except:
print('ERROR: Could not remove: \"{failed}\"'.format(failed = currentPath))
finally:
return True
return False
cleaner(r'/path/to/parent/dir')
I would really appreciate if somebody could show me how to integrate such functionality into the sub-routine. Cheers.
EDIT: Removed error handling as per request
def cleaner(currentPath):
if sys.platform == 'darwin':
os.system('chflags nouchg {}'.format(currentPath))
if not os.path.isdir(currentPath):
if currentPath.endswith(REMOVE_FILETYPES) or os.path.basename(currentPath).startswith('.'):
try:
os.remove(currentPath)
print('REMOVED: \"{removed}\"'.format(removed=currentPath))
except PermissionError:
if sys.platform == 'darwin':
os.system('chflags nouchg {}'.format(currentPath))
os.remove(currentPath)
if all([cleaner(os.path.join(currentPath, file)) for file in os.listdir(currentPath)]) and not currentPath == SOURCE_DIR:
os.rmdir(currentPath)
print('REMOVED: \"{removed}\"'.format(removed=currentPath))
Solution
You can unlock the file with the chflags
command:
os.system('chflags nouchg {}'.format(filename))
(There is a function os.chflags
, but the flag associated with the locked status is not a regular one, but what the os
module documentation calls a "user-defined" flag, as you can see by looking at os.stat(locked_filename).st_flags
.)
To solve your problem I'd add the chflags
command above to a specific except:
for the error you get trying to remove a locked file, along with a platform check:
try:
os.remove(currentPath)
print('REMOVED: \"{removed}\"'.format(removed = currentPath))
except PermissionError:
if sys.platform == 'darwin':
os.system('chflags nouchg {}'.format(currentPath))
os.remove(currentPath)
else:
raise
except BaseException as e:
...
Answered By - Nathan VÄ“rzemnieks
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.