การไล่สำรวจไดเรกทอรีและค้นหาไฟล์
os.walk(), รูปแบบ glob และการกรองไฟล์ตามประเภทหรือวันที่
การไล่สำรวจไดเรกทอรีและค้นหาไฟล์ เป็นบทเรียน AI Agents ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Agents และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน
เหตุผลที่เอเจนต์ต้องสำรวจไดเรกทอรี
เอเจนต์มักต้องค้นหาไฟล์ที่ตรงตามเงื่อนไขบางอย่าง เช่น ไฟล์ Python ทั้งหมดในฐานโค้ด ไฟล์ CSV ทั้งหมดในไดเรกทอรีข้อมูล หรือไฟล์บันทึกล่าสุดทั้งหมด Python มีเครื่องมือหลักสามอย่าง ได้แก่ os.walk(), Path.iterdir() และ Path.rglob() แต่ละอย่างมีจุดเด่นแตกต่างกัน ขึ้นอยู่กับความลึกที่คุณต้องการค้นหา
import os
from pathlib import Path
# Count all files in a directory tree
root = Path('/tmp/agent_workspace')
file_count = sum(1 for f in root.rglob('*') if f.is_file())
print(f'Found {file_count} files under {root}')os.walk() — การสำรวจไดเรกทอรีแบบเรียกซ้ำ
os.walk(root) จะส่งคืนทูเพิล (dirpath, dirnames, filenames) สำหรับทุกไดเรกทอรีในโครงสร้างต้นไม้ วิธีนี้เป็นแนวทางแบบดั้งเดิมของ Python สำหรับการสำรวจแบบเรียกซ้ำ และช่วยให้คุณควบคุมได้ละเอียดว่าจะลงไปยังไดเรกทอรีย่อยใดบ้าง
import os
import tempfile
# --- demo setup: build a small project tree so the walk has something to show ---
root = tempfile.mkdtemp(prefix='project_')
os.makedirs(os.path.join(root, 'src'), exist_ok=True)
os.makedirs(os.path.join(root, '.git'), exist_ok=True)
with open(os.path.join(root, 'README.md'), 'w') as f:
f.write('demo')
with open(os.path.join(root, 'src', 'main.py'), 'w') as f:
f.write('print(1)')
for dirpath, dirnames, filenames in os.walk(root):
# Skip hidden directories (like .git)
dirnames[:] = [d for d in dirnames if not d.startswith('.')]
print(f'In directory: {dirpath}')
print(f' Subdirs: {dirnames}')
print(f' Files: {filenames}')
for filename in filenames:
full_path = os.path.join(dirpath, filename)
print(f' File: {full_path}')
Path.iterdir() — การแสดงรายการระดับเดียว
Path.iterdir() แสดงเนื้อหาโดยตรงของไดเรกทอรี โดยจะไม่สำรวจเข้าไปในไดเรกทอรีย่อย ให้ใช้เมื่อคุณต้องการเฉพาะรายการย่อยโดยตรงของไดเรกทอรี และต้องการหลีกเลี่ยงการลงไปยังระดับที่ลึกกว่า
from pathlib import Path
data_dir = Path('data')
data_dir.mkdir(exist_ok=True)
(data_dir / 'a.csv').write_text('x')
(data_dir / 'sub').mkdir(exist_ok=True)
for item in data_dir.iterdir():
if item.is_file():
print(f'FILE: {item.name} ({item.stat().st_size} bytes)')
elif item.is_dir():
print(f'DIR: {item.name}/')
csv_files = [f for f in data_dir.iterdir()
if f.is_file() and f.suffix == '.csv']
print(f'Found {len(csv_files)} CSV files')Path.rglob() — การค้นหาแบบโกลบซ้ำ
Path.rglob(pattern) ค้นหาไฟล์ทั้งหมดที่ตรงกับรูปแบบการค้นหาแบบโกลบโดยสำรวจแบบเรียกซ้ำ วิธีนี้เป็นวิธีที่กระชับที่สุดในการค้นหาไฟล์ทุกไฟล์ของชนิดที่กำหนดไม่ว่าจะอยู่ที่ใดในโครงสร้างไดเรกทอรี เครื่องหมาย ** ในโกลบหมายถึง «ไดเรกทอรีจำนวนเท่าใดก็ได้»
from pathlib import Path
project = Path('/tmp/my_project')
# Find all Python files recursively
python_files = list(project.rglob('*.py'))
print(f'Found {len(python_files)} Python files:')
for f in python_files:
print(f' {f.relative_to(project)}')
# Find all JSON files
json_files = list(project.rglob('*.json'))
# Find files matching a name pattern
test_files = list(project.rglob('test_*.py'))
print(f'Found {len(test_files)} test files')glob.glob() — การจับคู่รูปแบบ
glob.glob(pattern, recursive=True) เป็นส่วนติดต่อแบบโกลบดั้งเดิม เมื่อใช้ recursive=True อักขระตัวแทน ** จะจับคู่กับพาธไดเรกทอรีย่อยใด ๆ ก็ได้ ฟังก์ชันนี้ส่งคืนสตริง ในขณะที่ pathlib.rglob ส่งคืนวัตถุ Path
import glob
# Find all CSV files recursively
csv_files = glob.glob('data/**/*.csv', recursive=True)
print(f'Found {len(csv_files)} CSV files')
for f in csv_files:
print(f' {f}')
# Find all log files in a specific directory (non-recursive)
logs = glob.glob('/var/log/*.log')
# Find files matching multiple criteria
import fnmatch
all_files = glob.glob('/tmp/**/*', recursive=True)
config_files = [
f for f in all_files
if fnmatch.fnmatch(f, '*.yaml') or fnmatch.fnmatch(f, '*.yml')
]
print(f'Found {len(config_files)} YAML config files')การกรองตามนามสกุลไฟล์
ขณะสำรวจไดเรกทอรี ให้กรองไฟล์ตามนามสกุลด้วย Path.suffix (ซึ่งรวมจุดไว้ด้วย เช่น '.py') หรือเปรียบเทียบกับชุดนามสกุลที่อนุญาต วิธีนี้ทำงานได้เร็วและแม่นยำกว่ารูปแบบโกลบเมื่อจำเป็นต้องกรองหลายนามสกุล
from pathlib import Path
directory = Path('/tmp/mixed_files')
ALLOWED_EXTENSIONS = {'.py', '.js', '.ts', '.json', '.yaml'}
# Filter by allowed extensions
code_files = [
f for f in directory.rglob('*')
if f.is_file() and f.suffix.lower() in ALLOWED_EXTENSIONS
]
print(f'Found {len(code_files)} code/config files')
# Group files by extension
from collections import defaultdict
by_ext = defaultdict(list)
for f in directory.rglob('*'):
if f.is_file():
by_ext[f.suffix].append(f)
for ext, files in sorted(by_ext.items()):
print(f'{ext}: {len(files)} files')การกรองตามขนาดไฟล์
บางครั้งเอเจนต์ต้องค้นหาไฟล์ที่มีขนาดสูงหรือต่ำกว่าเกณฑ์ เช่น ข้ามไฟล์ว่างขนาดเล็ก หรือหลีกเลี่ยงการประมวลผลไฟล์ขนาดใหญ่จนใช้หน่วยความจำมากเกินไป ให้ใช้ Path.stat().st_size เพื่อรับขนาดไฟล์เป็นไบต์
from pathlib import Path
data_dir = Path('/tmp/data')
MIN_SIZE = 1024 # 1 KB — skip empty/tiny files
MAX_SIZE = 50_000_000 # 50 MB — skip very large files
processable = []
skipped_small = []
skipped_large = []
for f in data_dir.rglob('*.json'):
if not f.is_file():
continue
size = f.stat().st_size
if size < MIN_SIZE:
skipped_small.append(f.name)
elif size > MAX_SIZE:
skipped_large.append(f.name)
else:
processable.append(f)
print(f'Processable: {len(processable)}')
print(f'Too small: {len(skipped_small)}')
print(f'Too large: {len(skipped_large)}')การกรองตามเวลาที่แก้ไข
เอเจนต์ในกระบวนการแบบเพิ่มทีละส่วนจำเป็นต้องประมวลผลเฉพาะไฟล์ที่เปลี่ยนแปลงนับจากการทำงานครั้งล่าสุดเท่านั้น ใช้ stat().st_mtime (เวลาที่แก้ไขในรูปค่าประทับเวลา Unix) เพื่อค้นหาไฟล์ที่เพิ่งถูกแก้ไข
from pathlib import Path
import time
import datetime
data_dir = Path('/tmp/data')
# Files modified in the last 24 hours
cutoff = time.time() - (24 * 60 * 60)
recent_files = [
f for f in data_dir.rglob('*.log')
if f.is_file() and f.stat().st_mtime > cutoff
]
print(f'Modified in last 24h: {len(recent_files)} files')
# Sort by modification time (newest first)
recent_files.sort(key=lambda f: f.stat().st_mtime, reverse=True)
for f in recent_files[:5]: # top 5 most recent
mtime = datetime.datetime.fromtimestamp(f.stat().st_mtime)
print(f' {f.name}: {mtime.strftime("%Y-%m-%d %H:%M:%S")}')การข้ามไฟล์ซ่อนและไดเรกทอรีระบบ
ขณะสำรวจคลังโค้ดหรือไดเรกทอรีของผู้ใช้ ให้ข้ามไฟล์ซ่อน (ที่ขึ้นต้นด้วย .) และไดเรกทอรีระบบ เช่น .git, __pycache__, node_modules และ .venv เนื้อหาเหล่านี้มีไฟล์หลายพันไฟล์ซึ่งไม่เกี่ยวข้องกับเอเจนต์ส่วนใหญ่
from pathlib import Path
SKIP_DIRS = {'.git', '__pycache__', 'node_modules', '.venv',
'.env', 'dist', 'build', '.mypy_cache'}
def iter_source_files(root, extensions):
root = Path(root)
for path in root.rglob('*'):
# Skip if any parent is in SKIP_DIRS
if any(part in SKIP_DIRS for part in path.parts):
continue
# Skip hidden files
if path.name.startswith('.'):
continue
if path.is_file() and path.suffix in extensions:
yield path
python_files = list(iter_source_files('/tmp/project', {'.py'}))
print(f'Found {len(python_files)} Python source files')การสร้างบัญชีรายการไฟล์
บัญชีรายการไฟล์คือสรุปแบบมีโครงสร้างของโครงสร้างต้นไม้ไดเรกทอรี ซึ่งมีประโยชน์สำหรับเอเจนต์ที่ต้องวางแผนงานก่อนประมวลผล ให้รวบรวมชื่อ พาธ ขนาด นามสกุล และเวลาที่แก้ไขลงในรายการพจนานุกรมที่สามารถแปลงเป็น JSON ได้
from pathlib import Path
import datetime
import json
def build_inventory(root_dir, pattern='**/*'):
root = Path(root_dir)
inventory = []
for f in root.glob(pattern):
if not f.is_file():
continue
stat = f.stat()
inventory.append({
'name': f.name,
'path': str(f.relative_to(root)),
'extension': f.suffix,
'size_bytes': stat.st_size,
'modified': datetime.datetime.fromtimestamp(
stat.st_mtime
).isoformat()
})
return sorted(inventory, key=lambda x: x['path'])
inventory = build_inventory('/tmp/data')
with open('file_inventory.json', 'w') as out:
json.dump(inventory, out, indent=2)
print(f'Inventoried {len(inventory)} files')การเฝ้าดูไดเรกทอรีเพื่อดูการเปลี่ยนแปลง
เอเจนต์บางประเภทจำเป็นต้องตอบสนองเมื่อมีไฟล์ใหม่ปรากฏในไดเรกทอรี แม้ไลบรารีเฝ้าดูไฟล์เต็มรูปแบบอย่าง watchdog จะเหมาะที่สุดสำหรับการใช้งานจริง แต่แนวทางง่าย ๆ คือสแกนไดเรกทอรีเป็นระยะและเปรียบเทียบกับชุดไฟล์ที่ทราบอยู่แล้ว
from pathlib import Path
import time
def watch_for_new_files(watch_dir, extension='.json', interval=5):
watch_dir = Path(watch_dir)
known_files = set(watch_dir.glob(f'*{extension}'))
print(f'Watching {watch_dir} for new {extension} files...')
while True:
time.sleep(interval)
current_files = set(watch_dir.glob(f'*{extension}'))
new_files = current_files - known_files
for f in new_files:
print(f'New file detected: {f.name}')
process_new_file(f) # handle the new file
known_files = current_files
def process_new_file(file_path):
print(f'Processing: {file_path}')
# --- demo (one polling cycle, without the infinite while True loop) ---
import tempfile
demo_dir = Path(tempfile.mkdtemp())
known_files = set(demo_dir.glob('*.json'))
print(f'Watching {demo_dir} for new .json files...')
(demo_dir / 'result_a.json').write_text('{}', encoding='utf-8')
(demo_dir / 'result_b.json').write_text('{}', encoding='utf-8')
current_files = set(demo_dir.glob('*.json'))
new_files = current_files - known_files
for f in sorted(new_files, key=lambda p: p.name):
print(f'New file detected: {f.name}')
process_new_file(f)
ตรวจสอบความเข้าใจ: rglob กับ iterdir
ทดสอบความเข้าใจเกี่ยวกับวิธีสำรวจไดเรกทอรี
สรุปการสำรวจไดเรกทอรี
ขณะนี้คุณสามารถค้นหาไฟล์ใด ๆ ที่เอเจนต์ต้องการได้แล้ว:
- os.walk() — ควบคุมการสำรวจแบบเรียกซ้ำได้อย่างเต็มที่ แก้ไข
dirnamesโดยตรงเพื่อไม่สำรวจไดเรกทอรีย่อยบางส่วน - Path.iterdir() — แสดงรายการระดับเดียวของรายการย่อยโดยตรง
- Path.rglob('*.ext') — การค้นหาแบบเรียกซ้ำตามรูปแบบที่สะอาดที่สุด
- glob.glob('**/*.ext', recursive=True) — ทางเลือกแบบดั้งเดิมที่ส่งคืนสตริง
- กรองตาม
.suffixสำหรับนามสกุล ตาม.stat().st_sizeสำหรับขนาด และตาม.stat().st_mtimeสำหรับเวลาที่แก้ไข - ข้ามไฟล์ซ่อนและไดเรกทอรีระบบ เช่น
.gitและnode_modulesเสมอ
คำถามที่พบบ่อย
บทเรียน “การไล่สำรวจไดเรกทอรีและค้นหาไฟล์” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การไล่สำรวจไดเรกทอรีและค้นหาไฟล์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Agents ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การไล่สำรวจไดเรกทอรีและค้นหาไฟล์”
os.walk(), รูปแบบ glob และการกรองไฟล์ตามประเภทหรือวันที่ คุณปฏิบัติ AI Agents ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Agents หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Agents บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “การไล่สำรวจไดเรกทอรีและค้นหาไฟล์” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Agents นี้ได้ไหม
ได้ บทเรียน AI Agents ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การอ่านและเขียนไฟล์ในบริบทของตัวแทน
- การไล่สำรวจไดเรกทอรีและค้นหาไฟล์
- การจัดการรูปแบบไฟล์: CSV, JSON และ TXT
- การดำเนินการกับไฟล์อย่างปลอดภัยพร้อมจัดการข้อผิดพลาด