Получение имен файлов без расширений файлов с помощью glob

Я ищу только файлы .txt

from glob import glob
result = glob('*.txt')

>> result
['text1.txt','text2.txt','text3.txt']

но я бы хотел result без расширений файлов

>> result
['text1','text2','text3']

Есть ли шаблон регулярного выражения, который я могу использовать с glob, чтобы исключить расширения файлов из вывода, или мне нужно использовать понимание списка для result?


person HappyPy    schedule 18.06.2018    source источник
comment
Ваш заголовок немного вводит в заблуждение, Getting file names without file extension with glob будет лучше?   -  person Simon    schedule 18.06.2018
comment
@ Саймон Согласен. Само название звучит так, будто оно ищет libmagic или какой-то другой эвристический способ обнаружения текстовых файлов. И ваша переписка звучит хорошо для меня.   -  person abarnert    schedule 18.06.2018
comment
@abarnert Должен ли я редактировать это сам? Без согласия ОП?   -  person Simon    schedule 18.06.2018
comment
В качестве примечания: glob не принимает шаблоны регулярных выражений, он использует шаблоны глобусов, а это совсем другое. Под прикрытием он создает шаблоны регулярных выражений для применения к списку файлов, но вы их не видите. (Если вы хотите их увидеть, см. модуль fnmatch.)   -  person abarnert    schedule 18.06.2018
comment
@ Саймон, я думаю, это нормально. ОП всегда может вернуться, если они не согласны, а если нет, вы улучшили их вопрос для них.   -  person abarnert    schedule 18.06.2018


Ответы (6)


Невозможно сделать это с glob(), вам нужно взять указанный список, а затем создать новый для хранения значений без расширения:

import os
from glob import glob

[os.path.splitext(val)[0] for val in glob('*.txt')]

os.path.splitext(val) разбивает имена файлов на имена файлов и расширения. [0] просто возвращает имена файлов.

person Simon    schedule 18.06.2018

Поскольку вы пытаетесь отделить расширение имени файла, а не произвольную строку, имеет смысл использовать os.path.splitext (или модуль pathlib ). Хотя это и не имеет практического значения для единственных значимых в настоящее время платформ (Windows и *nix), концептуально все же понятнее, что вы делаете. (И если вы позже начнете использовать объекты, подобные пути, вместо строк, он продолжит работать без изменений, для загрузки.)

So:

paths = [os.path.splitext(path)[0] for path in paths]

Между тем, если это действительно вас оскорбляет по какой-то причине, то, что glob делает под прикрытием, просто вызывает fnmatch, чтобы преобразовать ваше выражение glob в регулярное выражение, а затем применяет это ко всем именам файлов. Таким образом, вы можете заменить его, просто заменив регулярное выражение и используя группы захвата:

rtxt = re.compile(r'(.*?)\.txt')
files = (rtxt.match(file) for file in os.listdir(dirpath))
files = [match.group(1) for match in files if match]

Таким образом, вы не выполняете компоновку списка поверх того, что уже находится в glob; вы делаете один вместо того, что уже есть в glob. Я не уверен, полезная это победа или нет, но поскольку вы, кажется, заинтересованы в устранении listcomp...

person abarnert    schedule 18.06.2018
comment
@abanert: Спасибо за подробное объяснение. - person HappyPy; 18.06.2018

Используйте нарезку индекса:

result = [i[:-4] for i in result]
person Scott Boston    schedule 18.06.2018
comment
Это работает, но не так ясно и надежно, как использование splitext или даже rsplit. Если позже вы измените код так, чтобы он принимал как .txt, так и .text, например, другие решения продолжат работать, а это — нет. - person abarnert; 18.06.2018

Другой способ с использованием rsplit:

>>> result = ['text1.txt','text2.txt.txt','text3.txt']
>>> [x.rsplit('.txt', 1)[0] for x in result]
['text1', 'text2.txt', 'text3']

Вы можете сделать это как понимание списка:

result = [x.rsplit(".txt", 1)[0] for x in glob('*.txt')]
person Austin    schedule 18.06.2018
comment
Почему бы не просто rsplit('.')? - person abarnert; 18.06.2018
comment
@abarnert уверен, что это тоже работает. Но я думаю, что лучше использовать .txt, поскольку OP специфичен для файлов .txt. - person Austin; 18.06.2018

Этот глобус выбирает только файлы без расширения: **/*/!(*.*)

person Christiaan Maks    schedule 13.01.2020

Используйте 1_

>>> result = [r.split('.')[0] for r in glob('*.txt')]
>>> result
['text1', 'text2', 'text3']
person Sunitha    schedule 18.06.2018
comment
Это сделает неправильную вещь, скажем, для text.file.10.txt, вернув text вместо text.file.10 (что было бы правильно на некоторых устаревших платформах, но не на Windows или Unix). - person abarnert; 18.06.2018