4

In python3, when operating on unknown (user-input) file paths, I need to support wildcards such as ./r*/*.dat. The plan was to use something like this (simplified):

paths = []
for test in userinputs:
   paths.extend(pathlib.Path().glob(test))

This works great for relative paths; however, when the user provides an absolute path (which they should be allowed to do), the code fails:

NotImplementedError: Non-relative patterns are unsupported

If it's a "simple" glob, like /usr/bin/*, I can do something like:

test = pathlib.Path("/usr/bin/*")
sources.extend(test.parent.glob(test.name))

However, like my first path example, I need to account for wildcards in any of the parts of the path, such as /usr/b*/*.

Is there an elegant solution for this? I feel like I'm missing something obvious.

Michael
  • 145
  • 1
  • 8
  • 1
    `Path()` takes a parameter for its starting dir. why not test the input to see if an absolute path and then init `Path()` as the root dir? – Nullman May 26 '19 at 08:02
  • @Nullman That's it! Thank you so much. Please add this as an answer so I can mark it as such! – Michael May 26 '19 at 08:24

3 Answers3

2

Path() takes a parameter for its starting dir.
Why not test the input to see if an absolute path and then init Path() as the root dir? something like:

for test in userinputs:
    if test[0] == '/':
        paths.extend(pathlib.Path('/').glob(test[1:]))
    else:
        paths.extend(pathlib.Path().glob(test))
Nullman
  • 4,179
  • 2
  • 14
  • 30
  • 2
    That's what I needed! Thank you! For better cross-platform compatibility, I'm using that method this way: `paths.extend(pathlib.Path(path.anchor).glob(str(path.relative_to(path.anchor))))` Note I need to convert the Path object to a string for the glob for some reason; otherwise I get an error about being unable to convert it to lowercase(?) on Windows. – Michael May 26 '19 at 19:04
2

Is there a reason you can't use glob.glob?

import glob
paths = []
for test in userinputs:
   # 'glob' returns strings relative to the glob expression,
   # so convert these into the format returned by Path.glob
   # (use iglob since the output is just fed to a generator)
   extras = (Path(p).absolute() for p in glob.iglob(test))
   paths.extend(extras)
ntjess
  • 570
  • 6
  • 10
1

As an addendum to Nullman's answer:

pathlib.Path.is_absolute() might be a good cross-platform option.

via https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.is_absolute

  • 1
    Hi and welcome to SO. Please take the time to review the [How to answer section](https://stackoverflow.com/help/how-to-answer) in order to post a good, self contained answer that addresses the question. – Daniel Ocando Dec 18 '19 at 16:20
  • 2
    Hi Daniel - thanks for the link I'll take a look - I was intending to post as a comment on Nullman's answer but alas the SO points system... – armoured-moose Dec 18 '19 at 22:27