برای ایجاد دایرکتوری‌های جدید در سیستم فایل، کتابخانه std::filesystem دو تابع اصلی ارائه می‌دهد که تفاوت مهمی در نحوه‌ی عملکرد آنها وجود دارد. تابع create_directory یک دایرکتوری جدید در مسیر مشخص شده ایجاد می‌کند، اما شرط مهم آن این است که دایرکتوری والد (Parent Directory) از پیش وجود داشته باشد و در صورت عدم وجود، عملیات با خطا مواجه می‌شود . در مقابل، تابع create_directories (با فرم جمع) بسیار منعطف‌تر عمل کرده و تمام دایرکتوری‌های مسیر مشخص‌شده را که هنوز وجود ندارند، به‌صورت یکجا و به‌صورت بازگشتی ایجاد می‌کند؛ به‌گونه‌ای که اگر "a/b/c" را به آن بدهید، دایرکتوری‌های a، b و c را به‌ترتیب می‌سازد . یک نکته‌ی ظریف در استفاده از این توابع این است که اگر مسیر مورد نظر از قبل به‌عنوان یک دایرکتوری معتبر وجود داشته باشد، تابع هیچ خطایی گزارش نمی‌دهد و صرفاً مقدار false را بازمی‌گرداند که این رفتار، امکان استفاده‌ی ایمن از آنها را در سناریوهای مختلف فراهم می‌کند .

تکنیک کپی کردن ویژگی‌ها

برای ایجاد یک دایرکتوری جدید با ویژگی‌های مشابه یک دایرکتوری از پیش موجود، نسخه‌ی دومی از تابع create_directory وجود دارد که یک مسیر existing_p را به‌عنوان مرجع دریافت می‌کند . این تابع بسیار کاربردی است، به‌ویژه زمانی که نیاز به حفظ مجوزهای دسترسی (Permissions) یکسان در یک ساختار دایرکتوری جدید داریم. در سیستم‌های مبتنی بر POSIX (مانند لینوکس و مک)، ویژگی‌هایی مانند مجوزها از مسیر مرجع کپی می‌شوند، اما در سیستم‌عامل ویندوز، ویژگی‌ها کپی نمی‌شوند و این تفاوت به ماهیت سیستم‌عامل مربوط است . همچنین توجه به این نکته مهم است که این نسخه از تابع، به‌صورت خودکار توسط copy هنگام کپی بازگشتی دایرکتوری‌ها فراخوانی می‌شود .

پیمایش با directory_iterator

کلاس directory_iterator یک تکرارگر (Iterator) استاندارد برای پیمایش محتویات یک دایرکتوری (بدون ورود به زیردایرکتوری‌ها) است . این کلاس از حلقه‌های مبتنی بر محدوده (Range-based for loops) پشتیبانی کامل می‌کند که نوشتن کدهای پیمایش را به‌شدت ساده می‌سازد. مهم‌ترین نکته در مورد این تکرارگر، نوع مقدار (Value Type) آن است که directory_entry نام دارد و شامل اطلاعات کاملی درباره‌ی هر ورودی دایرکتوری است . همچنین این تکرارگر به‌گونه‌ای هوشمند طراحی شده که ورودی‌های ویژه‌ی . و .. را نادیده می‌گیرد و تنها روی ورودی‌های واقعی تمرکز می‌کند . یک نکته‌ی بسیار کاربردی در مورد directory_iterator این است که بسیاری از پیاده‌سازی‌های سیستمعامل، هنگام بازگشت هر ورودی، ویژگی‌های آن را نیز دریافت می‌کنند (مانند نوع فایل یا اندازه) و این کلاس از این قابلیت برای ذخیره‌سازی این اطلاعات در directory_entry استفاده می‌کند، به‌طوری که در حین پیمایش، نیازی به فراخوانی سیستم‌های اضافی برای دریافت ویژگی‌های فایل نیست و این امر باعث افزایش چشمگیر سرعت کار می‌شود .

پیمایش بازگشتی با recursive_directory_iterator

اگر نیاز به پیمایش تمام محتویات یک دایرکتوری به‌همراه تمام زیرشاخه‌های آن دارید، recursive_directory_iterator ابزار مناسب شماست . این تکرارگر نیز از حلقه‌های مبتنی بر محدوده پشتیبانی کرده و تمام ورودی‌های سلسله‌مراتب را یک‌بار بازدید می‌کند . یکی از قابلیت‌های جالب آن، متد depth() است که عمق جاری را در ساختار دایرکتوری بازمی‌گرداند؛ دایرکتوری ریشه دارای عمق ۰، زیردایرکتوری‌های مستقیم آن دارای عمق ۱ و به‌همین ترتیب ادامه می‌یابد . این قابلیت در تولید خروجی‌های درختی با فاصله‌گذاری مناسب بسیار کاربرد دارد . همچنین این کلاس دارای قابلیت‌های کنترلی مانند disable_recursion_pending() است که امکان توقف موقت ورود به زیرشاخه‌ی جاری را فراهم می‌کند .

بررسی نوع و ویژگی‌های ورودی‌ها

هر ورودی از نوع directory_entry که توسط تکرارگرها بازگردانده می‌شود، مجموعه‌ی کاملی از متدها را برای بررسی ویژگی‌های فایل یا دایرکتوری مربوطه در اختیار برنامه‌نویس قرار می‌دهد . مهم‌ترین این متدها عبارتند از: is_directory() برای تشخیص دایرکتوری بودن، is_regular_file() برای تشخیص فایل معمولی بودن (که برای عملیات خواندن و نوشتن کاربرد دارد)، is_symlink() برای تشخیص پیوند سمبلیک، و همچنین متدهای دیگری مانند is_block_file() و is_character_file() . همچنین متد file_size() برای دریافت حجم فایل و last_write_time() برای دریافت زمان آخرین تغییر، از جمله امکانات مفید دیگر این کلاس هستند . این متدها در دو نسخه وجود دارند: یکی که در صورت بروز خطا استثنا پرتاب می‌کند و دیگری که یک شیء error_code را برای بررسی دریافت می‌کند . وجود این ابزارها به برنامه‌نویس اجازه می‌دهد تا منطق پیچیده‌ای مانند فیلتر کردن فایل‌ها بر اساس نوع، اندازه یا زمان تغییر را به‌سادگی پیاده‌سازی کند و به عنوان مثال، تنها فایل‌های متنی بزرگ‌تر از یک حد مشخص را پردازش نماید .

کلیدواژه ها : std::filesystem-ایجاد دایرکتوری در C++-create_directory-create_directories-پیمایش دایرکتوری C++-directory_iterator-recursive_directory_iterator-std::filesystem depth-directory_entry-بررسی نوع فایل C++-is_regular_file-is_directory-پیمایش بازگشتی پوشه-C++17 filesystem-مدیریت دایرکتوری در C++-آموزش std::filesystem-کپی ویژگی‌های دایرکتوری