глобус виключити візерунок


103

У мене є каталог з купою файлів всередині: eee2314, asd3442... і eph.

Я хочу , щоб виключити всі файли , які починаються з ephз globфункцією.

Як я можу це зробити?

Відповіді:


146

Правила шаблону для glob не є регулярними виразами. Натомість вони дотримуються стандартних правил розширення шляху Unix. Спеціальних символів лише кілька: два різні символи підстановки та підтримуються діапазони символів [від glob ].

Таким чином, ви можете виключити деякі файли з візерунками.
Наприклад, щоб виключити файли маніфестів (файли, що починаються з _) за допомогою glob, ви можете використовувати:

files = glob.glob('files_path/[!_]*')

10
Це має бути в офіційній документації, будь-хто додайте це до docs.python.org/3.5/library/glob.html#glob.glob
Віталій Зданевич

6
Зауважте, що шаблони глобусів не можуть безпосередньо заповнити вимогу, встановлену ОП: виключати лише файли, які починаються з, ephале можуть починатися з чогось іншого. [!e][!p][!h]буде фільтрувати файли, які починаються, eeeнаприклад.
Мартін Пітерс

60

Ви можете вирахувати набори:

set(glob("*")) - set(glob("eph*"))

3
Дійсно цікаве рішення! Але моя справа буде надзвичайно повільною, щоб прочитати двічі. Крім того, якщо вміст папки великий у мережевому каталозі, це знову буде повільним. Але в будь-якому випадку, дуже зручно.
Анастасіос Андронідіс

Ваша операційна система повинна кешувати запити файлової системи, так не так вже й погано :)
neutrinus

Спробував це сам, я щойно отримав TypeError: непідтримувані типи операндів для -: 'list' і 'list'
Tom Busby

1
@TomBusby Спробуйте перетворити їх на набори: set(glob("*")) - set(glob("eph*")) (і зауважте * в кінці "eph *")
Jaszczur

2
Подібно до додаткової примітки, glob повертає списки, а не множини, але така операція працює лише на множинах, отже, чому нейтринус відкидає її. Якщо вам потрібно, щоб він залишився в списку, просто оберніть всю операцію в гіпс:list(set(glob("*")) - set(glob("eph")))
Натан Сміт

48

Ви не можете виключити шаблони за допомогою globфункції, глобуси дозволяють лише шаблони включення . Глобальний синтаксис дуже обмежений (навіть [!..]клас символів повинен відповідати символу, тому це шаблон включення для кожного символу, якого немає в класі).

Вам доведеться зробити власну фільтрацію; розуміння списку зазвичай тут добре працює:

files = [fn for fn in glob('somepath/*.txt') 
         if not os.path.basename(fn).startswith('eph')]

3
Використовуйте iglobтут, щоб уникнути збереження повного списку в пам'яті
Євген Панков

3
@Hardex: всередині, все одноiglob створює списки ; все, що ви робите - це ліниво оцінювати фільтр. Це не допоможе зменшити обсяг пам'яті.
Мартін Пітерс

@Hardex: якщо ви використовуєте глобус в назві каталогу, тоді у вас буде точка, тоді щонайбільше один os.listdir()результат зберігається в пам'яті під час ітерації. Але somepath/*.txtвін повинен прочитати всі імена файлів в одному каталозі в пам'яті, а потім зменшити цей список лише до тих, що відповідають.
Мартін Пітерс

Ви маєте рацію, це не так уже й важливо, але в наявності CPython, glob.glob(x) = list(glob.iglob(x)). Не багато накладних витрат, але все одно корисно знати.
Євген Панков

Це не повторюється двічі ?. Один раз через файли отримати список, а другий - через сам список? Якщо так, то чи не можна це зробити за одну ітерацію?
Рідхуваршан

6

Пізно до гри, але ви можете просто застосувати пітон 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']

5

Як щодо пропуску певного файлу під час ітерації всіх файлів у папці! Нижче код пропускає всі файли 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)

Таким чином ви можете використовувати більш складні шаблони регулярних виразів, щоб включити / виключити певний набір файлів у папці.


5

Порівняйте 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.


4

Більш загально, щоб виключити файли, які не відповідають деякому регулярному виразу оболонки, ви можете використовувати модуль 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)

Вище описане спочатку генерує список із заданого шляху, а потім вискакує файли, які не задовольняють регулярному виразу з необхідним обмеженням.


Це має бути прийнятою відповіддю.
Філіп Ремі,

0

Як згадується у прийнятій відповіді, ви не можете виключити шаблони за допомогою 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*"))

(У моєму випадку у мене було кілька кадрів зображень, кадрів зсуву та плоских кадрів - все в одному каталозі, і я просто хотів, щоб вони були в кадрі)


0

Якщо позиція символу не важлива, тобто, наприклад, для виключення файлів маніфестів (скрізь, де він знайдений _) за допомогою 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)

-1

Ви можете скористатися наведеним нижче способом:

# 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.  
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.