获取 Path 对象的 "true" 主干的简洁方法?
Clean way to get the "true" stem of a Path object?
预期的输入和输出:
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
上中断:
>>> 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)
谢谢。
一个 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)
请注意,当 example_path.suffixes
returns 空列表时 while 循环退出循环(因为空列表在布尔上下文中为 False)。
Example/Demo -
>>> 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'
你可以 .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
这是给定问题的另一种可能解决方案:
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
如果你想单独使用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'
另一种方法使用模式匹配:
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())
如果您的所有路径至少有一个后缀,则可以使用模式“[.]”
为什么不递归?
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')
预期的输入和输出:
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
上中断:
>>> 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)
谢谢。
一个 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)
请注意,当 example_path.suffixes
returns 空列表时 while 循环退出循环(因为空列表在布尔上下文中为 False)。
Example/Demo -
>>> 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'
你可以 .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
这是给定问题的另一种可能解决方案:
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
如果你想单独使用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'
另一种方法使用模式匹配:
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())
如果您的所有路径至少有一个后缀,则可以使用模式“[.]”
为什么不递归?
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')