راه
۴ کیو· سختپیشرفتهPYTHON۴ ثانیه · ۲۵۶ مگابایت

مدیریت فایل‌ها

هدف این تمرین، پیاده‌سازی یک کلاس پایتونی برای مدیریت ابتدایی فایل‌ها و پوشه‌ها در سیستم عامل است. این مدیر فایل باید قابلیت‌های اصلی زیر را ارائه دهد:

  • ایجاد یک پوشه‌ی جدید در یک مسیر مشخص
  • ایجاد یک فایل جدید در یک مسیر مشخص
  • جست‌وجوی فایل‌ها بر اساس نام در یک مسیر و زیرشاخه‌های آن
  • حذف یک فایل از یک مسیر مشخص
  • بازیابی فایل‌های حذف‌شده

📄 کلاس FileManager

🔹 create_dir(self, name, address)

یک پوشه‌ی جدید با نام name در مسیر address می‌سازد. خروجی‌ای ندارد. اگر پوشه از قبل وجود داشته باشد، هیچ عملیاتی انجام نمی‌شود.

🔹 create_file(self, name, address)

یک فایل جدید با نام name در مسیر address ایجاد می‌کند. خروجی‌ای ندارد. اگر فایل از قبل وجود داشته باشد، هیچ عملیاتی انجام نمی‌شود.

🔹 delete(self, name, address)

فایلی با نام name را از مسیر address حذف می‌کند. خروجی‌ای ندارد. اگر فایلی در مسیر address با نام name وجود نداشته باشد، هیچ عملیاتی انجام نمی‌شود.

🔹 find(self, name, address)

لیست کامل مسیرهای تمام فایل‌های با نام name را از مسیر address به بعد برمی‌گرداند. جست‌وجو باید شامل خود مسیر address و تمام زیرشاخه‌های آن باشد. ترتیب مسیرها در لیست خروجی اهمیتی ندارد. اگر هیچ فایلی با این نام یافت نشود، یک لیست خالی [] برگردانده می‌شود.

🔹 restore(self, name)

آخرین فایلی که با نام name حذف شده‌است را بازیابی می‌کند و به مسیر اصلی خود بازمی‌گرداند. عملیات بازیابی به‌صورت LIFO (Last-In, First-Out) بر اساس نام فایل عمل می‌کند. محتوای اصلی فایل حذف شده باید پس از بازیابی دست‌نخورده باقی بماند. اگر هیچ فایلی با نام name در لیست فایل‌های حذف‌شده موجود نباشد، هیچ عملیاتی انجام نمی‌شود.

برای حل این سؤال می‌توانید هر فایل و یا پوشه‌ی موقتی که خواستید در کنار فایل کدتان بسازید. فایل‌های حذف‌شده باید در یک سطل زباله (Trash) موقت ذخیره شوند تا امکان بازیابی وجود داشته باشد.


📖 مثال

بخش ۱: ایجاد ساختار

python
fm = FileManager()

# ساختار اولیه
fm.create_dir('test_fm', '.')
fm.create_dir('test1', 'test_fm')
fm.create_dir('test2', 'test_fm/test1')

# ایجاد فایل‌ها
fm.create_file('document.txt', 'test_fm')
fm.create_file('document.txt', 'test_fm/test1')
fm.create_file('document.txt', 'test_fm/test1/test2')
fm.create_file('another.txt', 'test_fm')
text
test_fm/
    ├── test1/
        │   ├── test2/
            │   │   └── document.txt
        │   └── document.txt
    ├── document.txt
    └── another.txt

بخش ۲: جست‌وجو

python
print(fm.find('document.txt', 'test_fm'))

📤 خروجی

python
['test_fm/document.txt', 'test_fm/test1/document.txt', 'test_fm/test1/test2/document.txt']

بخش ۳: حذف فایل‌ها

python
fm.delete('document.txt', 'test_fm')
fm.delete('document.txt', 'test_fm/test1/')
fm.delete('document.txt', 'test_fm/test1/test2')
text
test_fm/
    ├── test1/
        │   └── test2/
    └── another.txt

بخش ۴: بازیابی فایل‌ها

python
fm.restore('document.txt')
fm.restore('document.txt')
text
test_fm/
    ├── test1/
        │   ├── test2/
            │   │   └── document.txt
        │   └── document.txt
    └── another.txt

بخش ۵: جست‌وجوی مجدد

python
print(fm.find('document.txt', 'test_fm'))

💡 فایل test_fm/document.txt بازیابی نشد چون آخرین فایلی نبود که حذف شده بود (LIFO).

python
['test_fm/test1/document.txt', 'test_fm/test1/test2/document.txt']

✅ پاسخ نهایی

python
import os
import shutil
import tempfile

class FileManager:
    def __init__(self):
        # دیکشنری برای ذخیره‌ی فایل‌های حذف‌شده به صورت LIFO بر اساس نام
        self.trash = {}
        # پوشه‌ی موقت برای ذخیره‌ی فایل‌های حذف‌شده
        self.trash_dir = tempfile.mkdtemp()

    def _get_full_path(self, address, name):
        if address == '.':
            return name
        return os.path.join(address, name)

    def create_dir(self, name, address):
        path = self._get_full_path(address, name)
        if not os.path.exists(path):
            os.makedirs(path, exist_ok=True)

    def create_file(self, name, address):
        path = self._get_full_path(address, name)
        if not os.path.exists(path):
            open(path, 'w').close()

    def delete(self, name, address):
        path = self._get_full_path(address, name)
        if os.path.exists(path) and os.path.isfile(path):
            # ذخیره‌سازی در سطل زباله
            if name not in self.trash:
                self.trash[name] = []

            # ایجاد یک نام یکتا برای فایل در سطل زباله
            trash_path = os.path.join(self.trash_dir, f"{name}_{len(self.trash[name])}")
            # کپی کردن فایل به سطل زباله (با حفظ محتوا)
            shutil.copy2(path, trash_path)
            self.trash[name].append({'trash_path': trash_path, 'original_path': path})
            # حذف فایل اصلی
            os.remove(path)

    def find(self, name, address):
        result = []
        for root, dirs, files in os.walk(address):
            if name in files:
                result.append(os.path.join(root, name))
        return result

    def restore(self, name):
        if name in self.trash and self.trash[name]:
            # LIFO: آخرین فایل اضافه‌شده را بازیابی می‌کند
            entry = self.trash[name].pop()
            trash_path = entry['trash_path']
            original_path = entry['original_path']

            # اطمینان از وجود پوشه‌ی مقصد
            os.path.dirname(original_path)
            os.makedirs(os.path.dirname(original_path), exist_ok=True)

            # بازیابی فایل به مسیر اصلی
            shutil.copy2(trash_path, original_path)

            # حذف فایل از سطل زباله
            os.remove(trash_path)

            # اگر لیست خالی شد، کلید را حذف می‌کنیم
            if not self.trash[name]:
                del self.trash[name]

📄 main.py


📖 توضیح کد

  • سطل زباله (Trash): از یک دیکشنری به نام trash استفاده شده که کلید آن نام فایل و مقدار آن لیستی از دیکشنری‌های شامل مسیر فایل در سطل زباله و مسیر اصلی است.
  • روش LIFO: با استفاده از pop() روی لیست، آخرین فایل اضافه‌شده برای هر نام بازیابی می‌شود.
  • متد _get_full_path: مسیر کامل یک فایل یا پوشه را با ترکیب address و name می‌سازد.
  • متد find: با استفاده از os.walk تمام زیرشاخه‌ها را پیمایش کرده و فایل‌های با نام مشخص را پیدا می‌کند.
  • متد delete: قبل از حذف، فایل را با shutil.copy2 به سطل زباله کپی می‌کند تا محتوا حفظ شود.
  • متد restore: فایل را از سطل زباله به مسیر اصلی بازمی‌گرداند.
  • از tempfile.mkdtemp() برای ایجاد پوشه‌ی موقت سطل زباله استفاده شده است
  • از shutil.copy2 برای کپی کردن فایل با حفظ متادیتا استفاده شده است
  • فایل‌های حذف‌شده با نام‌های یکتا در سطل زباله ذخیره می‌شوند تا از تداخل جلوگیری شود

🚀 پس از تکمیل کلاس، می‌توانید آن را با مثال‌های مختلف تست کنید و از صحت عملکرد آن اطمینان حاصل کنید.

نمونه‌ها

ورودی نمونه ۱
fm = FileManager()
fm.create_dir('test_fm', '.')
fm.create_dir('test1', 'test_fm')
fm.create_dir('test2', 'test_fm/test1')
fm.create_file('document.txt', 'test_fm')
fm.create_file('document.txt', 'test_fm/test1')
fm.create_file('document.txt', 'test_fm/test1/test2')
fm.create_file('another.txt', 'test_fm')
sorted(p.replace("\\", "/") for p in fm.find('document.txt', 'test_fm'))
fm.delete('document.txt', 'test_fm')
fm.delete('document.txt', 'test_fm/test1/')
fm.delete('document.txt', 'test_fm/test1/test2')
fm.find('document.txt', 'test_fm')
fm.restore('document.txt')
fm.restore('document.txt')
sorted(p.replace("\\", "/") for p in fm.find('document.txt', 'test_fm'))
خروجی نمونه ۱
['test_fm/document.txt', 'test_fm/test1/document.txt', 'test_fm/test1/test2/document.txt']
[]
['test_fm/test1/document.txt', 'test_fm/test1/test2/document.txt']
ورودی نمونه ۲
fm = FileManager()
fm.create_dir('d', '.')
fm.create_file('a.txt', 'd')
with open('d/a.txt', 'w') as handle:
    handle.write('keep me')
fm.create_file('a.txt', 'd')
fm.create_dir('d', '.')
open('d/a.txt').read()
خروجی نمونه ۲
'keep me'
ورودی نمونه ۳
fm = FileManager()
fm.create_dir('box', '.')
fm.delete('ghost.txt', 'box')
fm.restore('ghost.txt')
fm.find('ghost.txt', 'box')
خروجی نمونه ۳
[]
ورودی نمونه ۴
fm = FileManager()
fm.create_dir('keep', '.')
fm.create_file('note.txt', 'keep')
with open('keep/note.txt', 'w') as handle:
    handle.write('first draft')
fm.delete('note.txt', 'keep')
fm.find('note.txt', 'keep')
fm.restore('note.txt')
open('keep/note.txt').read()
خروجی نمونه ۴
[]
'first draft'

برای نوشتن پاسخ و دریافت امتیاز، ابتدا وارد حساب شوید.

ورود