0

Context

  • Writing Python to sort out/align NAS music library folder structure with mp3 tags (both folders and tags need fixes)
  • Parent folder mapped as /Volumes/Multimedia/Music/
  • Local machine is Macbook

Problem

  • There appears to be a bad/ghost folder on my QNAP NAS drive
  • Keeps appearing in results of path.glob('*/*.mp3')
  • Causes for fyl in path.glob('*/*.mp3'): to fail with FileNotFoundError

Options Tried

Stuff I've tried:

% ls T2*
ls: T2Y97F~A: No such file or directory
% rm -rf "T2Y97F~A"
% ls T2*           
ls: T2Y97F~A: No such file or directory

% find . -type d -name T2*
./T2Y97F~A
% ls "./T2Y97F~A"
ls: ./T2Y97F~A: No such file or directory

% rm -rf "./T2Y97F~A"
% find . -type d -name T2*
./T2Y97F~A

% find . -type d -name T2Y97F* -exec rm -rf {} +
find: ./T2Y97F~A: No such file or directory

...fail!

  • Ignore the error in python with try/except/continue...
##
# glob returns a bad/ghost folder that isn't fully recognised
# FileNotFoundError escapes from except block
# continue doesn't seem to work

import os, csv, logging
from pathlib import Path, PurePosixPath

# Configure Logging
logging.basicConfig(
    level=logging.INFO,
    filename= '' + PurePosixPath(__file__).stem + '.log', 
    format='%(asctime)s\t|\t|\t%(levelname)s\t|\t%(message)s'
    )

ctr = 0

dirSrc = '/Volumes/Multimedia/Music/' # then /{artist}/
path = Path(dirSrc)

# Get any immediate children of /{artist}/
# glob is a generator
for fyl in path.glob('*/*.mp3'):

    # Stop after 50 whilst in dev/test
    ctr = ctr + 1
    if ctr >= 50:
        break

    try:
        logging.info('Handling {}'.format(str(fyl)))
    except FileNotFoundError as e:
        logging.exception('Problem handling {src} because {e}'.format(src = str(fyl), e = e))
        continue # Carry on with for...loop
    except OSError as e:
        logging.exception('Problem handling {src} because {e}'.format(src = str(fyl), e = e))
        continue # Carry on with for...loop
    except Exception as e:
        logging.exception('Problem handling {src} because {e}'.format(src = str(fyl), e=e))

...running the above throws the following error to command line and stops at the error (i.e. doesn't get to ctr == 50)...

% python3 ./ghostFolder.py
Traceback (most recent call last):
  File "/Users/john_skelton/Workspaces/mp3tagging/./ghostFolder.py", line 24, in <module>
    for fyl in path.glob('*/*.mp3'):
  File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/pathlib.py", line 1034, in glob
    for p in selector.select_from(self):
  File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/pathlib.py", line 457, in _select_from
    for p in self.successor._select_from(path, is_dir, exists, scandir):
  File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/pathlib.py", line 440, in _select_from
    with scandir(parent_path) as scandir_it:
FileNotFoundError: [Errno 2] No such file or directory: '/Volumes/Multimedia/Music/T2Y97F~A'

...fail! I note that the code is failing on the iterator line itself (for...glob) - with glob being a generator, not a fixed set.

Help Requested

To achieve either/both of the following...

  • Delete the bad/ghost folder
  • Amend python code so that it will resume iteration if one file/item fails

Many thanks in anticipation :-)

JohnSk
  • 93
  • 1
  • 6

1 Answers1

0

OK, would still like answers to the above if there is a 'pure' answer. I did find a workaround - hence posting here as an answer rather than a comment/edit.

This comes from: glob exclude pattern.

allGoodFolders = list(set(path.glob("*")) - set(path.glob("T2Y97F~A")))
for dir in allGoodFolders:
    for f in dir.glob("*.mp3"):
        logging.info('All good - {}'.format(str(f)))

I don't think this 'iterate parent then iterate files' approach would work to structure the try/excepts (without the set - set) because the outer for dir in... would still fail and drop out of the iteration/generator.

Given this, I consider this a workaround because it's only feasible if the set - set isn't too costly on processing. Works for me (unexpectedly) but doesn't really satisfy.

Anything better?

JohnSk
  • 93
  • 1
  • 6