รูปแบบที่ไม่รวม glob


110

ฉันมีไดเร็กทอรีที่มีไฟล์มากมายอยู่ภายใน: eee2314, asd3442... และeph.

ฉันต้องการที่จะแยกไฟล์ทั้งหมดที่เริ่มต้นด้วยการephที่มีglobฟังก์ชั่น

ฉันจะทำมันได้อย่างไร?

คำตอบ:


162

กฎรูปแบบสำหรับ glob ไม่ใช่นิพจน์ทั่วไป แต่จะปฏิบัติตามกฎการขยายพา ธ Unix มาตรฐาน มีอักขระพิเศษเพียงไม่กี่ตัวเท่านั้น: ไวด์การ์ดสองแบบที่แตกต่างกันและช่วงอักขระได้รับการสนับสนุน [จากpymotw: glob - การจับคู่รูปแบบชื่อไฟล์ ]

คุณจึงสามารถยกเว้นไฟล์บางไฟล์ที่มีรูปแบบได้
ตัวอย่างเช่นในการยกเว้นไฟล์ Manifest (ไฟล์ที่ขึ้นต้นด้วย_) ด้วย glob คุณสามารถใช้:

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

10
ต้องอยู่ในเอกสารอย่างเป็นทางการโปรดเพิ่มข้อมูลนี้ในdocs.python.org/3.5/library/glob.html#glob.glob
Vitaly Zdanevich

8
โปรดทราบว่ารูปแบบ glob ไม่สามารถเติมเต็มความต้องการที่กำหนดโดย OP ได้โดยตรง: เพื่อยกเว้นเฉพาะไฟล์ที่ขึ้นต้นด้วยephแต่สามารถเริ่มต้นด้วยสิ่งอื่นได้ [!e][!p][!h]จะกรองไฟล์ที่ขึ้นต้นด้วยeeeเช่น
Martijn Pieters

60

คุณสามารถหักชุด:

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

4
ทางออกที่น่าสนใจจริงๆ! แต่กรณีของฉันจะช้ามากที่จะอ่านสองครั้ง นอกจากนี้หากเนื้อหาของโฟลเดอร์มีขนาดใหญ่บนไดเร็กทอรีเครือข่ายจะช้าอีกครั้ง แต่ในกรณีใด ๆ มีประโยชน์จริงๆ
Anastasios Andronidis

ระบบปฏิบัติการของคุณควรแคชการร้องขอระบบไฟล์ไม่ใช่เรื่องแย่ :)
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ฟังก์ชัน globs อนุญาตเฉพาะรูปแบบการรวมเท่านั้น ไวยากรณ์ Globbingมีข้อ จำกัด มาก (แม้แต่[!..]คลาสอักขระก็ต้องตรงกับอักขระดังนั้นจึงเป็นรูปแบบการรวมสำหรับอักขระทุกตัวที่ไม่ได้อยู่ในคลาส)

คุณจะต้องทำการกรองของคุณเอง ความเข้าใจในรายการมักใช้ได้ดีที่นี่:

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

3
ใช้iglobที่นี่เพื่อหลีกเลี่ยงการเก็บรายการทั้งหมดไว้ในหน่วยความจำ
Eugene Pankov

3
@ Hardex: ภายในiglobสร้างรายการต่อไป ; สิ่งที่คุณทำคือประเมินตัวกรองอย่างเกียจคร้าน จะไม่ช่วยลดรอยความจำ
Martijn Pieters

@Hardex: ถ้าคุณใช้ glob ในชื่อไดเร็กทอรีคุณจะมีจุดos.listdir()ผลลัพธ์ส่วนใหญ่จะถูกเก็บไว้ในหน่วยความจำเมื่อคุณทำซ้ำ แต่somepath/*.txtต้องอ่านชื่อไฟล์ทั้งหมดในไดเร็กทอรีเดียวในหน่วยความจำจากนั้นลดรายชื่อนั้นลงให้เหลือเฉพาะชื่อที่ตรงกัน
Martijn Pieters

คุณขวาก็ไม่ได้ว่าสิ่งที่สำคัญ แต่ในสต็อก glob.glob(x) = list(glob.iglob(x))CPython, ค่าใช้จ่ายไม่มาก แต่ก็ยังดีที่จะรู้
Eugene Pankov

ไม่ได้ทำซ้ำสองครั้ง? เมื่อผ่านไฟล์เพื่อรับรายการและที่สองผ่านรายการเอง? ถ้าเป็นเช่นนั้นจะทำซ้ำในครั้งเดียวไม่ได้หรือ?
Ridhuvarshan

6

มาถึงเกม แต่คุณสามารถใช้ python filterกับผลลัพธ์ของ a glob:

files = glob.iglob('your_path_here')
files_i_care_about = filter(lambda x: not x.startswith("eph"), files)

หรือแทนที่แลมด้าด้วยการค้นหา regex ที่เหมาะสม ฯลฯ ...

แก้ไข: ฉันเพิ่งรู้ว่าหากคุณใช้เส้นทางแบบเต็มstartswithจะไม่ได้ผลดังนั้นคุณต้องใช้ 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

วิธีการข้ามไฟล์ใดไฟล์หนึ่งในขณะที่วนซ้ำไฟล์ทั้งหมดในโฟลเดอร์! โค้ดด้านล่างจะข้ามไฟล์ 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)

ด้วยวิธีนี้คุณสามารถใช้รูปแบบ regex ที่ซับซ้อนมากขึ้นเพื่อรวม / ไม่รวมชุดไฟล์เฉพาะในโฟลเดอร์


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

ใช้รหัสที่คุณสามารถกรองไฟล์ทั้งหมดที่เริ่มต้นด้วยหรือเริ่มต้นด้วยephepi


4

โดยทั่วไปหากต้องการยกเว้นไฟล์ที่ไม่สอดคล้องกับเชลล์ regexp คุณสามารถใช้โมดูล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 ของคุณ

คำตอบที่ยอมรับน่าจะเป็นวิธี pythonic ที่ดีที่สุดในการทำสิ่งต่างๆ แต่ถ้าคุณคิดว่าความเข้าใจในรายการดูน่าเกลียดไปหน่อยและต้องการทำให้โค้ดของคุณเป็นตัวเลขสูงสุดอยู่ดี (เหมือนที่ฉันทำ) คุณสามารถทำได้ (แต่โปรดทราบว่านี่อาจมีประสิทธิภาพน้อยกว่า กว่าวิธีการเข้าใจรายการ):

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

หากตำแหน่งของอักขระไม่สำคัญตัวอย่างเช่นในการยกเว้นไฟล์ Manifest (ทุกที่ที่พบ_) ด้วย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.  
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.