ฉันมีไดเร็กทอรีที่มีไฟล์มากมายอยู่ภายใน: eee2314
, asd3442
... และeph
.
ฉันต้องการที่จะแยกไฟล์ทั้งหมดที่เริ่มต้นด้วยการeph
ที่มีglob
ฟังก์ชั่น
ฉันจะทำมันได้อย่างไร?
ฉันมีไดเร็กทอรีที่มีไฟล์มากมายอยู่ภายใน: eee2314
, asd3442
... และeph
.
ฉันต้องการที่จะแยกไฟล์ทั้งหมดที่เริ่มต้นด้วยการeph
ที่มีglob
ฟังก์ชั่น
ฉันจะทำมันได้อย่างไร?
คำตอบ:
กฎรูปแบบสำหรับ glob ไม่ใช่นิพจน์ทั่วไป แต่จะปฏิบัติตามกฎการขยายพา ธ Unix มาตรฐาน มีอักขระพิเศษเพียงไม่กี่ตัวเท่านั้น: ไวด์การ์ดสองแบบที่แตกต่างกันและช่วงอักขระได้รับการสนับสนุน [จากpymotw: glob - การจับคู่รูปแบบชื่อไฟล์ ]
คุณจึงสามารถยกเว้นไฟล์บางไฟล์ที่มีรูปแบบได้
ตัวอย่างเช่นในการยกเว้นไฟล์ Manifest (ไฟล์ที่ขึ้นต้นด้วย_
) ด้วย glob คุณสามารถใช้:
files = glob.glob('files_path/[!_]*')
eph
แต่สามารถเริ่มต้นด้วยสิ่งอื่นได้ [!e][!p][!h]
จะกรองไฟล์ที่ขึ้นต้นด้วยeee
เช่น
คุณสามารถหักชุด:
set(glob("*")) - set(glob("eph*"))
set(glob("*")) - set(glob("eph*"))
(และสังเกต * ที่ท้าย "eph *")
list(set(glob("*")) - set(glob("eph")))
คุณไม่สามารถยกเว้นรูปแบบด้วยglob
ฟังก์ชัน globs อนุญาตเฉพาะรูปแบบการรวมเท่านั้น ไวยากรณ์ Globbingมีข้อ จำกัด มาก (แม้แต่[!..]
คลาสอักขระก็ต้องตรงกับอักขระดังนั้นจึงเป็นรูปแบบการรวมสำหรับอักขระทุกตัวที่ไม่ได้อยู่ในคลาส)
คุณจะต้องทำการกรองของคุณเอง ความเข้าใจในรายการมักใช้ได้ดีที่นี่:
files = [fn for fn in glob('somepath/*.txt')
if not os.path.basename(fn).startswith('eph')]
iglob
ที่นี่เพื่อหลีกเลี่ยงการเก็บรายการทั้งหมดไว้ในหน่วยความจำ
iglob
สร้างรายการต่อไป ; สิ่งที่คุณทำคือประเมินตัวกรองอย่างเกียจคร้าน จะไม่ช่วยลดรอยความจำ
os.listdir()
ผลลัพธ์ส่วนใหญ่จะถูกเก็บไว้ในหน่วยความจำเมื่อคุณทำซ้ำ แต่somepath/*.txt
ต้องอ่านชื่อไฟล์ทั้งหมดในไดเร็กทอรีเดียวในหน่วยความจำจากนั้นลดรายชื่อนั้นลงให้เหลือเฉพาะชื่อที่ตรงกัน
glob.glob(x) = list(glob.iglob(x))
CPython, ค่าใช้จ่ายไม่มาก แต่ก็ยังดีที่จะรู้
มาถึงเกม แต่คุณสามารถใช้ 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']
วิธีการข้ามไฟล์ใดไฟล์หนึ่งในขณะที่วนซ้ำไฟล์ทั้งหมดในโฟลเดอร์! โค้ดด้านล่างจะข้ามไฟล์ 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 ที่ซับซ้อนมากขึ้นเพื่อรวม / ไม่รวมชุดไฟล์เฉพาะในโฟลเดอร์
เปรียบเทียบกับ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
โดยทั่วไปหากต้องการยกเว้นไฟล์ที่ไม่สอดคล้องกับเชลล์ 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)
ขั้นแรกจะสร้างรายการจากเส้นทางที่กำหนดและไฟล์ถัดไปจะปรากฏขึ้นซึ่งไม่ตรงกับนิพจน์ทั่วไปด้วยข้อ จำกัด ที่ต้องการ
ดังที่ได้กล่าวไว้ในคำตอบที่ยอมรับคุณไม่สามารถยกเว้นรูปแบบด้วย 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*"))
(ในกรณีของฉันฉันมีเฟรมภาพเฟรมอคติและเฟรมแบนทั้งหมดในไดเรกทอรีเดียวและฉันแค่ต้องการเฟรมภาพ)
หากตำแหน่งของอักขระไม่สำคัญตัวอย่างเช่นในการยกเว้นไฟล์ 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)
คุณสามารถใช้วิธีการด้านล่าง:
# 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.