У мене є каталог з купою файлів всередині: eee2314
, asd3442
... і eph
.
Я хочу , щоб виключити всі файли , які починаються з eph
з glob
функцією.
Як я можу це зробити?
У мене є каталог з купою файлів всередині: eee2314
, asd3442
... і eph
.
Я хочу , щоб виключити всі файли , які починаються з eph
з glob
функцією.
Як я можу це зробити?
Відповіді:
Правила шаблону для glob не є регулярними виразами. Натомість вони дотримуються стандартних правил розширення шляху Unix. Спеціальних символів лише кілька: два різні символи підстановки та підтримуються діапазони символів [від glob ].
Таким чином, ви можете виключити деякі файли з візерунками.
Наприклад, щоб виключити файли маніфестів (файли, що починаються з _
) за допомогою glob, ви можете використовувати:
files = glob.glob('files_path/[!_]*')
eph
але можуть починатися з чогось іншого. [!e][!p][!h]
буде фільтрувати файли, які починаються, eee
наприклад.
Ви можете вирахувати набори:
set(glob("*")) - set(glob("eph*"))
set(glob("*")) - set(glob("eph*"))
(і зауважте * в кінці "eph *")
list(set(glob("*")) - set(glob("eph")))
Ви не можете виключити шаблони за допомогою glob
функції, глобуси дозволяють лише шаблони включення . Глобальний синтаксис дуже обмежений (навіть [!..]
клас символів повинен відповідати символу, тому це шаблон включення для кожного символу, якого немає в класі).
Вам доведеться зробити власну фільтрацію; розуміння списку зазвичай тут добре працює:
files = [fn for fn in glob('somepath/*.txt')
if not os.path.basename(fn).startswith('eph')]
iglob
тут, щоб уникнути збереження повного списку в пам'яті
iglob
створює списки ; все, що ви робите - це ліниво оцінювати фільтр. Це не допоможе зменшити обсяг пам'яті.
os.listdir()
результат зберігається в пам'яті під час ітерації. Але somepath/*.txt
він повинен прочитати всі імена файлів в одному каталозі в пам'яті, а потім зменшити цей список лише до тих, що відповідають.
glob.glob(x) = list(glob.iglob(x))
. Не багато накладних витрат, але все одно корисно знати.
Пізно до гри, але ви можете просто застосувати пітон filter
до результату glob
:
files = glob.iglob('your_path_here')
files_i_care_about = filter(lambda x: not x.startswith("eph"), files)
або заміна лямбди на відповідний пошук регулярних виразів тощо ...
EDIT: Я щойно зрозумів, що якщо ви використовуєте повні шляхи, це startswith
не буде працювати, тож вам знадобиться регулярний вираз
In [10]: a
Out[10]: ['/some/path/foo', 'some/path/bar', 'some/path/eph_thing']
In [11]: filter(lambda x: not re.search('/eph', x), a)
Out[11]: ['/some/path/foo', 'some/path/bar']
Як щодо пропуску певного файлу під час ітерації всіх файлів у папці! Нижче код пропускає всі файли Excel, які починаються на "eph"
import glob
import re
for file in glob.glob('*.xlsx'):
if re.match('eph.*\.xlsx',file):
continue
else:
#do your stuff here
print(file)
Таким чином ви можете використовувати більш складні шаблони регулярних виразів, щоб включити / виключити певний набір файлів у папці.
Порівняйте glob
, рекомендую pathlib
, фільтрувати один шаблон дуже просто.
from pathlib import Path
p = Path(YOUR_PATH)
filtered = [x for x in p.glob("**/*") if not x.name.startswith("eph")]
і якщо ви хочете відфільтрувати більш складний шаблон, ви можете визначити для цього функцію, як:
def not_in_pattern(x):
return (not x.name.startswith("eph")) and not x.name.startswith("epi")
filtered = [x for x in p.glob("**/*") if not_in_pattern(x)]
використовуючи цей код, ви можете відфільтрувати всі файли, які починаються з eph
або починаються з epi
.
Більш загально, щоб виключити файли, які не відповідають деякому регулярному виразу оболонки, ви можете використовувати модуль fnmatch
:
import fnmatch
file_list = glob('somepath')
for ind, ii in enumerate(file_list):
if not fnmatch.fnmatch(ii, 'bash_regexp_with_exclude'):
file_list.pop(ind)
Вище описане спочатку генерує список із заданого шляху, а потім вискакує файли, які не задовольняють регулярному виразу з необхідним обмеженням.
Як згадується у прийнятій відповіді, ви не можете виключити шаблони за допомогою glob, тому нижче наведено метод фільтрації результату glob.
Прийнята відповідь - це, мабуть, найкращий пітонічний спосіб зробити щось, але якщо ви вважаєте, що розуміння списку виглядає трохи потворно і хочете зробити свій код максимально нуміфонічним (як я це зробив), тоді ви можете це зробити (але зауважте, що це, мабуть, менш ефективно ніж метод розуміння списку):
import glob
data_files = glob.glob("path_to_files/*.fits")
light_files = np.setdiff1d( data_files, glob.glob("*BIAS*"))
light_files = np.setdiff1d(light_files, glob.glob("*FLAT*"))
(У моєму випадку у мене було кілька кадрів зображень, кадрів зсуву та плоских кадрів - все в одному каталозі, і я просто хотів, щоб вони були в кадрі)
Якщо позиція символу не важлива, тобто, наприклад, для виключення файлів маніфестів (скрізь, де він знайдений _
) за допомогою glob
та re
- операцій регулярного виразу , ви можете використовувати:
import glob
import re
for file in glob.glob('*.txt'):
if re.match(r'.*\_.*', file):
continue
else:
print(file)
Або з більш елегантним способом - list comprehension
filtered = [f for f in glob.glob('*.txt') if not re.match(r'.*\_.*', f)]
for mach in filtered:
print(mach)
Ви можете скористатися наведеним нижче способом:
# Get all the files
allFiles = glob.glob("*")
# Files starting with eph
ephFiles = glob.glob("eph*")
# Files which doesnt start with eph
noephFiles = []
for file in allFiles:
if file not in ephFiles:
noephFiles.append(file)
# noepchFiles has all the file which doesnt start with eph.
Thank you.