20

预期输入和输出:

a                 -> a
a.txt             -> a
archive.tar.gz    -> archive
directory/file    -> file
d.x.y.z/f.a.b.c   -> f
logs/date.log.txt -> date # Mine!

这是我觉得很脏的实现:

>>> from pathlib import Path
>>> example_path = Path("August 08 2015, 01'37'30.log.txt")
>>> example_path.stem
"August 08 2015, 01'37'30.log"
>>> example_path.suffixes
['.log', '.txt']
>>> suffixes_length = sum(map(len, example_path.suffixes))
>>> true_stem = example_path.name[:-suffixes_length]
>>> true_stem
"August 08 2015, 01'37'30"

因为它在Path没有后缀的 s 上中断:

>>> ns_path = Path("no_suffix")
>>> sl = sum(map(len, ns_path.suffixes))
>>> ns_path.name[:-sl]
''

所以我需要先检查是否Path有后缀:

>>> def get_true_stem(path: Path):
...     if path.suffix:
...         sl = sum(map(len, path.suffixes))
...         return path.name[:-sl]
...     else:
...         return path.stem
...
>>>
>>> get_true_stem(example_path)
"August 08, 2015, 01'37'30"
>>> get_true_stem(ns_path)
"no_suffix"

这是我当前的用例:

>>> file_date = datetime.strptime(true_stem, "%B %d %Y, %H'%M'%S")
>>> file_date
datetime.datetime(2015, 8, 8, 1, 37, 30)
>>> new_dest = format(file_date, "%Y-%m-%dT%H:%M:%S%z") + ".log" # ISO-8601
>>> shutil.move(str(example_path), new_dest)

谢谢。

4

6 回答 6

22

你可以.split这样:

>>> Path('logs/date.log.txt').stem.split('.')[0]
'date'

os.path也可以:

>>> os.path.basename('logs/date.log.txt').split('.')[0]
'date'

它通过了所有测试:

In [11]: all(Path(k).stem.split('.')[0] == v for k, v in {
   ....:     'a': 'a',
   ....:     'a.txt': 'a',
   ....:     'archive.tar.gz': 'archive',
   ....:     'directory/file': 'file',
   ....:     'd.x.y.z/f.a.b.c': 'f',
   ....:     'logs/date.log.txt': 'date'
   ....: }.items())
Out[11]: True
于 2015-08-08T06:35:26.460 回答
6

一个while循环方法怎么样,你一直在.stem使用直到路径没有后缀,例如 -

from pathlib import Path
example_path = Path("August 08 2015, 01'37'30.log.txt")
example_path_stem = example_path.stem
while example_path.suffixes:
    example_path_stem = example_path.stem
    example_path = Path(example_path_stem)

请注意,while 循环在example_path.suffixes返回一个空列表时退出循环(因为空列表是 False,就像在布尔上下文中一样)。


示例/演示 -

>>> from pathlib import Path
>>> example_path = Path("August 08 2015, 01'37'30.log.txt")
>>> example_path_stem = example_path.stem
>>> while example_path.suffixes:
...     example_path_stem = example_path.stem
...     example_path = Path(example_path_stem)
...
>>> example_path_stem
"August 08 2015, 01'37'30"

对于您的第二个输入 - no_suffix-

>>> example_path = Path("no_suffix")
>>> example_path_stem = example_path.stem
>>> while example_path.suffixes:
...     example_path_stem = example_path.stem
...     example_path = Path(example_path_stem)
...
>>> example_path_stem
'no_suffix'
于 2015-08-08T06:35:02.400 回答
4

这是给定问题的另一种可能的解决方案:

from pathlib import Path

if __name__ == '__main__':
    dataset = [
        ('a', 'a'),
        ('a.txt', 'a'),
        ('archive.tar.gz', 'archive'),
        ('directory/file', 'file'),
        ('d.x.y.z/f.a.b.c', 'f'),
        ('logs/date.log.txt', 'date'),
    ]
    for path, stem in dataset:
        path = Path(path)
        assert path.name.replace("".join(path.suffixes), "") == stem
于 2020-04-04T16:05:03.830 回答
2

为什么不递归呢?

from pathlib import Path

def true_stem(path):
   stem = Path(path).stem
   return stem if stem == path else true_stem(stem)

assert(true_stem('d.x.y.z/f.a.b.c') == 'f')
于 2021-06-30T09:18:17.573 回答
1

如果您想唯一地使用 pathlib,您还可以使用:

>>> Path('logs/date.log.txt').with_suffix('').stem
'date'

编辑:

正如评论中所指出的,如果您的扩展名超过 2 个后缀,这将不起作用。虽然这听起来不太可能(并且 pathlib 本身没有处理它的本地方法),但如果您想唯一地使用 pathlib,您可以使用:

>>> Path('logs/date.log.txt.foo').with_suffix('').with_suffix('').stem
'date'
于 2020-07-18T19:09:52.843 回答
1

另一种方法使用模式匹配:

import re
from pathlib import Path
all(re.search('[.]|',Path(k).name) for k,v in {
   'a': 'a',
   'a.txt': 'a',
   'archive.tar.gz': 'archive',
   'directory/file': 'file',
   'd.x.y.z/f.a.b.c': 'f',
   'logs/date.log.txt': 'date'
   }.items())

如果您的所有路径都至少有一个后缀,则可以使用模式“[.]”

于 2021-02-17T18:10:14.943 回答