Tôi có một thư mục với một loạt các tập tin bên trong: eee2314
, asd3442
... và eph
.
Tôi muốn loại bỏ tất cả các file bắt đầu bằng eph
với glob
chức năng.
Tôi làm nó như thế nào?
Tôi có một thư mục với một loạt các tập tin bên trong: eee2314
, asd3442
... và eph
.
Tôi muốn loại bỏ tất cả các file bắt đầu bằng eph
với glob
chức năng.
Tôi làm nó như thế nào?
Câu trả lời:
Các quy tắc mẫu cho cầu không phải là biểu thức chính quy. Thay vào đó, chúng tuân theo các quy tắc mở rộng đường dẫn Unix tiêu chuẩn. Chỉ có một số ký tự đặc biệt: hai ký tự đại diện khác nhau và phạm vi ký tự được hỗ trợ [từ cầu ].
Vì vậy, bạn có thể loại trừ một số tệp có mẫu.
Ví dụ: để loại trừ các tệp kê khai (tệp bắt đầu bằng _
) với hình cầu, bạn có thể sử dụng:
files = glob.glob('files_path/[!_]*')
eph
nhưng có thể bắt đầu bằng bất kỳ thứ gì khác. [!e][!p][!h]
sẽ lọc ra các tệp bắt đầu bằng eee
ví dụ.
Bạn có thể trừ các bộ:
set(glob("*")) - set(glob("eph*"))
set(glob("*")) - set(glob("eph*"))
(và thông báo * ở cuối "eph *")
list(set(glob("*")) - set(glob("eph")))
Bạn không thể loại trừ các mẫu bằng glob
hàm, các hình cầu chỉ cho phép các mẫu bao gồm . Cú pháp bóng bẩy rất hạn chế (thậm chí một [!..]
lớp ký tự phải khớp với một ký tự, vì vậy nó là một mẫu bao gồm cho mọi ký tự không có trong lớp).
Bạn sẽ phải thực hiện lọc của riêng mình; một cách hiểu danh sách thường hoạt động tốt ở đây:
files = [fn for fn in glob('somepath/*.txt')
if not os.path.basename(fn).startswith('eph')]
iglob
ở đây để tránh việc lưu trữ danh sách đầy đủ trong bộ nhớ
iglob
tạo ra danh sách nào ; tất cả những gì bạn làm là lười biếng đánh giá bộ lọc. Nó sẽ không giúp giảm dung lượng bộ nhớ.
os.listdir()
kết quả được lưu trong bộ nhớ khi bạn lặp lại. Nhưng somepath/*.txt
phải đọc tất cả các tên tệp trong một thư mục trong bộ nhớ, sau đó giảm danh sách đó xuống chỉ những tên phù hợp.
glob.glob(x) = list(glob.iglob(x))
. Không có nhiều chi phí nhưng vẫn tốt để biết.
Cuối trò chơi nhưng bạn có thể chỉ cần áp dụng một con trăn filter
vào kết quả của một glob
:
files = glob.iglob('your_path_here')
files_i_care_about = filter(lambda x: not x.startswith("eph"), files)
hoặc thay thế lambda bằng một tìm kiếm regex thích hợp, v.v.
CHỈNH SỬA: Tôi vừa nhận ra rằng nếu bạn đang sử dụng các đường dẫn đầy đủ, startswith
nó sẽ không hoạt động, vì vậy bạn cần một regex
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']
Làm thế nào về việc bỏ qua tệp cụ thể trong khi lặp lại tất cả các tệp trong thư mục! Đoạn mã dưới đây sẽ bỏ qua tất cả các tệp excel bắt đầu bằng '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)
Bằng cách này, bạn có thể sử dụng các mẫu regex phức tạp hơn để bao gồm / loại trừ một tập hợp tệp cụ thể trong một thư mục.
glob
Tôi khuyên bạn nên so sánh với pathlib
bộ lọc một mẫu rất đơn giản.
from pathlib import Path
p = Path(YOUR_PATH)
filtered = [x for x in p.glob("**/*") if not x.name.startswith("eph")]
và nếu bạn muốn lọc mẫu phức tạp hơn, bạn có thể xác định một hàm để làm điều đó, giống như:
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)]
sử dụng mã đó, bạn có thể lọc tất cả các tệp bắt đầu bằng eph
hoặc bắt đầu bằng epi
.
Nói chung, để loại trừ các tệp không tuân thủ một số shell regexp, bạn có thể sử dụng mô-đun 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)
Ở trên, đầu tiên sẽ tạo một danh sách từ một đường dẫn nhất định và tiếp theo sẽ xuất hiện các tệp không đáp ứng biểu thức chính quy với ràng buộc mong muốn.
Như đã đề cập trong câu trả lời được chấp nhận, bạn không thể loại trừ các mẫu có hình cầu, vì vậy sau đây là phương pháp để lọc kết quả toàn cầu của bạn.
Câu trả lời được chấp nhận có lẽ là cách tốt nhất để thực hiện công việc nhưng nếu bạn nghĩ rằng phần hiểu danh sách trông hơi xấu và muốn làm cho mã của bạn tối đa không có độ phức tạp (như tôi đã làm) thì bạn có thể làm điều này (nhưng lưu ý rằng điều này có thể kém hiệu quả hơn so với phương pháp hiểu danh sách):
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*"))
(Trong trường hợp của tôi, tôi có một số khung hình ảnh, khung hình thiên vị và khung hình phẳng tất cả trong một thư mục và tôi chỉ muốn các khung hình ảnh)
Nếu vị trí của ký tự không quan trọng, chẳng hạn như để loại trừ tệp kê khai (bất cứ nơi nào tìm thấy _
) với các phép toán glob
và re
- biểu thức chính quy , bạn có thể sử dụng:
import glob
import re
for file in glob.glob('*.txt'):
if re.match(r'.*\_.*', file):
continue
else:
print(file)
Hoặc theo một cách thanh lịch hơn - list comprehension
filtered = [f for f in glob.glob('*.txt') if not re.match(r'.*\_.*', f)]
for mach in filtered:
print(mach)
Bạn có thể sử dụng phương pháp dưới đây:
# 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.