mô hình loại trừ toàn cầu


103

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 ephvới globchức năng.

Tôi làm nó như thế nào?

Câu trả lời:


147

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/[!_]*')

10
Đây phải có ít tài liệu chính thức, xin vui lòng ai đó thêm video này vào docs.python.org/3.5/library/glob.html#glob.glob
Vitaly Zdanevich

6
Lưu ý rằng các mẫu hình cầu không thể hoàn thành trực tiếp yêu cầu do OP đặt ra: chỉ loại trừ các tệp bắt đầu bằng ephnhư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 eeeví dụ.
Martijn Pieters

60

Bạn có thể trừ các bộ:

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

3
Giải pháp thực sự thú vị! Nhưng trường hợp của tôi sẽ cực kỳ chậm để đọc hai lần. Ngoài ra, nếu nội dung của một thư mục lớn trên một thư mục mạng, nó sẽ lại chậm. Nhưng trong mọi trường hợp, thực sự tiện dụng.
Anastasios Andronidis

Hệ điều hành của bạn nên bộ nhớ cache hệ thống tập tin yêu cầu vì vậy không quá tệ :)
neutrinus

Cố gắng này bản thân mình, tôi chỉ nhận được Lỗi Loại: không được hỗ trợ loại toán hạng (s) cho -: 'danh sách' và 'danh sách'
Tom Busby

1
@TomBusby Hãy thử chuyển đổi chúng thành bộ: set(glob("*")) - set(glob("eph*")) (và thông báo * ở cuối "eph *")
Jaszczur

2
Cũng giống như một lưu ý bên lề, global trả về danh sách chứ không phải tập hợp, nhưng kiểu hoạt động này chỉ hoạt động trên tập hợp, do đó, tại sao neutrinus truyền nó. Nếu bạn cần nó để duy trì một danh sách, bạn chỉ cần quấn toàn bộ hoạt động trong một dàn diễn viên:list(set(glob("*")) - set(glob("eph")))
Nathan Smith

48

Bạn không thể loại trừ các mẫu bằng globhà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')]

3
Sử dụng iglobở đây để tránh việc lưu trữ danh sách đầy đủ trong bộ nhớ
Eugene Pankov

3
@Hardex: trong nội bộ, iglobtạ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ớ.
Martijn Pieters

@Hardex: nếu bạn sử dụng một hình cầu trong tên thư mục thì bạn sẽ có một điểm, sau đó nhiều nhất một os.listdir()kết quả được lưu trong bộ nhớ khi bạn lặp lại. Nhưng somepath/*.txtphả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.
Martijn Pieters

bạn nói đúng, nó không quan trọng lắm, nhưng trong CPython cổ phiếu , glob.glob(x) = list(glob.iglob(x)). Không có nhiều chi phí nhưng vẫn tốt để biết.
Eugene Pankov

Điều này không lặp lại hai lần? Một lần thông qua các tệp để có được danh sách và lần thứ hai thông qua chính danh sách? Nếu vậy, có phải là không thể thực hiện nó trong một lần lặp lại?
Ridhuvarshan

6

Cuối trò chơi nhưng bạn có thể chỉ cần áp dụng một con trăn filtervà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 đủ, startswithnó 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']

5

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.


5

globTôi khuyên bạn nên so sánh với pathlibbộ 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 ephhoặc bắt đầu bằng epi.


4

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.


Đây phải là câu trả lời được chấp nhận.
Philippe Remy

0

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)


0

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 globre- 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)

-1

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.  
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.