Mam katalog z bandą plików wewnątrz: eee2314
, asd3442
... a eph
.
Chcę wykluczyć wszystkie pliki, które zaczynają eph
się od glob
funkcji.
Jak mogę to zrobić?
Mam katalog z bandą plików wewnątrz: eee2314
, asd3442
... a eph
.
Chcę wykluczyć wszystkie pliki, które zaczynają eph
się od glob
funkcji.
Jak mogę to zrobić?
Odpowiedzi:
Reguły wzorców dla glob nie są wyrażeniami regularnymi. Zamiast tego stosują się do standardowych reguł rozwijania ścieżek w systemie Unix. Jest tylko kilka znaków specjalnych: dwa różne symbole wieloznaczne i obsługiwane są zakresy znaków [z pymotw: glob - dopasowanie wzorca nazwy pliku ].
Możesz więc wykluczyć niektóre pliki z wzorami.
Na przykład, aby wykluczyć pliki manifestów (pliki zaczynające się od _
) z glob, możesz użyć:
files = glob.glob('files_path/[!_]*')
eph
ale mogą zaczynać się od czegoś innego. [!e][!p][!h]
odfiltruje pliki zaczynające się eee
na przykład od.
Możesz odliczyć zestawy:
set(glob("*")) - set(glob("eph*"))
set(glob("*")) - set(glob("eph*"))
(i zauważ * na końcu „eph *”)
list(set(glob("*")) - set(glob("eph")))
Nie możesz wykluczyć wzorców za pomocą glob
funkcji, globy pozwalają tylko na włączanie wzorców. Składnia globbingu jest bardzo ograniczona (nawet [!..]
klasa znaków musi pasować do znaku, więc jest to wzorzec włączenia dla każdego znaku, którego nie ma w klasie).
Będziesz musiał wykonać własne filtrowanie; rozumienie listy zwykle dobrze działa tutaj:
files = [fn for fn in glob('somepath/*.txt')
if not os.path.basename(fn).startswith('eph')]
iglob
tutaj, aby uniknąć przechowywania pełnej listy w pamięci
iglob
tworzy listy ; wszystko co robisz to leniwie oceniasz filtr. Nie pomoże to w zmniejszeniu zużycia pamięci.
os.listdir()
wynik jest przechowywany w pamięci podczas iteracji. Ale somepath/*.txt
musi czytać wszystkie nazwy plików w jednym katalogu w pamięci, a następnie zredukować tę listę do tylko tych, które pasują.
glob.glob(x) = list(glob.iglob(x))
. Niewielkie koszty, ale dobrze wiedzieć.
Spóźniony do gry, ale alternatywnie możesz po prostu zastosować Pythona filter
do wyniku glob
:
files = glob.iglob('your_path_here')
files_i_care_about = filter(lambda x: not x.startswith("eph"), files)
lub zastąpienie lambdy odpowiednim wyszukiwaniem wyrażeń regularnych itp.
EDYCJA: Właśnie zdałem sobie sprawę, że jeśli używasz pełnych ścieżek startswith
, nie zadziała, więc potrzebujesz wyrażenia regularnego
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']
Co powiesz na pominięcie konkretnego pliku podczas iteracji po wszystkich plikach w folderze! Poniższy kod pomija wszystkie pliki Excela zaczynające się od „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)
W ten sposób możesz użyć bardziej złożonych wzorców regex, aby uwzględnić / wykluczyć określony zestaw plików w folderze.
Porównaj z glob
, polecam pathlib
, filtr jeden wzorzec jest bardzo prosty.
from pathlib import Path
p = Path(YOUR_PATH)
filtered = [x for x in p.glob("**/*") if not x.name.startswith("eph")]
a jeśli chcesz filtrować bardziej złożony wzorzec, możesz zdefiniować funkcję, która to zrobi, tak jak:
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)]
użyj tego kodu, możesz filtrować wszystkie pliki, które zaczynają się od eph
lub zaczynają się od epi
.
Bardziej ogólnie, aby wykluczyć pliki, które nie są zgodne z niektórymi wyrażeniami regularnymi powłoki, możesz użyć modułu 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)
Powyższe najpierw wygeneruje listę z podanej ścieżki, a następnie wyskoczy pliki, które nie spełnią wyrażenia regularnego z żądanym ograniczeniem.
Jak wspomniano w akceptowanej odpowiedzi, nie możesz wykluczyć wzorców za pomocą glob, więc poniżej przedstawiono metodę filtrowania wyniku glob.
Przyjęta odpowiedź jest prawdopodobnie najlepszym Pythonowym sposobem robienia rzeczy, ale jeśli uważasz, że listy składane wyglądają trochę brzydko i chcesz, aby Twój kod i tak był maksymalnie numpythonic (tak jak ja), możesz to zrobić (ale pamiętaj, że jest to prawdopodobnie mniej wydajne niż metoda rozumienia listy):
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*"))
(W moim przypadku miałem kilka ramek obrazów, ramek odchylenia i płaskich ramek w jednym katalogu i chciałem tylko ramki obrazów)
Jeśli pozycja znaku nie jest ważna, to znaczy na przykład, aby wykluczyć pliki manifestów (gdziekolwiek zostanie znaleziony _
) za pomocą glob
i re
- operacji wyrażeń regularnych , możesz użyć:
import glob
import re
for file in glob.glob('*.txt'):
if re.match(r'.*\_.*', file):
continue
else:
print(file)
Lub w bardziej elegancki sposób - list comprehension
filtered = [f for f in glob.glob('*.txt') if not re.match(r'.*\_.*', f)]
for mach in filtered:
print(mach)
Możesz użyć poniższej metody:
# 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.