परिचय: Rust में फ़ाइलों की लिस्ट क्यों ज़रूरी है?
\n\nसोचिए: आप Rust में बैकअप टूल, लॉग एनालाइज़र या एक साधारण फ़ाइल मैनेजर बना रहे हैं। तब एक बुनियादी लेकिन ज़रूरी काम आता है — किसी डायरेक्टरी की सभी फ़ाइलों की सूची प्राप्त करना। आसान लगता है? Rust की सख्त टाइपिंग और ओनरशिप सिस्टम में यह सरल काम भी कुछ चुनौतियाँ लाता है।
\n\nसवाल «How can I list files of a directory in Rust?» Stack Overflow पर सबसे लोकप्रिय में से एक है (हज़ारों व्यूज़!)। यह कोई संयोग नहीं: नए डेवलपर्स अक्सर std::fs::read_dir में उलझ जाते हैं, इटरेटर को समझने में गड़बड़ी करते हैं और एरर हैंडलिंग भूल जाते हैं। इस ट्यूटोरियल में मैं दो काम के तरीके दिखाऊँगा: सरल (एक फ़ोल्डर की फ़ाइलें) और एडवांस (सभी सब-डायरेक्टरी में रिकर्सिव ट्रैवर्सल)। चलिए शुरू करते हैं!
1. तैयारी: नया प्रोजेक्ट बनाएँ
\n\nकोड लिखने से पहले, एक नया बाइनरी प्रोजेक्ट बनाते हैं। टर्मिनल खोलें और यह चलाएँ:
\n\ncargo new list_files_rs\ncd list_files_rs\n\nअब src/main.rs खोलें — यहीं हम सारा कोड लिखेंगे। शुरुआत में किसी बाहरी डिपेंडेंसी की ज़रूरत नहीं, बस Rust की स्टैंडर्ड लाइब्रेरी — std काफी है।
2. सबसे आसान तरीका: std::fs::read_dir
\n\nstd::fs::read_dir फ़ंक्शन डायरेक्टरी की एंट्रीज़ पर एक इटरेटर लौटाता है। हर एंट्री एक DirEntry होती है, जिसमें नाम, पथ, टाइप और मेटाडेटा होता है। चलिए एक बेसिक उदाहरण लिखते हैं:
use std::fs;\nuse std::path::Path;\n\nfn main() -> Result<(), Box<dyn std::error::Error>> {\n let path = Path::new("."); // मौजूदा डायरेक्टरी\n\n // फ़ोल्डर की सामग्री पढ़ें\n let entries = fs::read_dir(path)?;\n\n for entry in entries {\n let entry = entry?; // Result को अनपैक करें\n let path = entry.path();\n\n // जाँचें कि यह फ़ाइल है (डायरेक्टरी नहीं)\n if path.is_file() {\n println!("{}", path.display());\n }\n }\n\n Ok(())\n}\n\nयहाँ क्या हो रहा है?
\n- \n
fs::read_dir(path)— डायरेक्टरी खोलता है औरReadDir(इटरेटर) लौटाता है। \n - हम हर एंट्री पर लूप चलाते हैं। हर
next()कॉलResult<DirEntry>लौटाता है — इसलिएentry?ज़रूरी है। \n entry.path()फ़ाइल/फ़ोल्डर का पूरा पथ लौटाता है। \n path.is_file()मेथड सब-डायरेक्टरी को हटा देता है। \n
कोड को cargo run से चलाएँ — आपको प्रोजेक्ट रूट की फ़ाइलें दिखेंगी (जैसे Cargo.toml, src/main.rs)।
2.1. एक्सटेंशन के अनुसार फ़िल्टर करें
\n\nअक्सर सिर्फ़ कुछ खास फ़ाइलें चाहिए, जैसे सिर्फ़ .rs या .txt। फ़िल्टर जोड़ते हैं:
use std::fs;\nuse std::path::Path;\n\nfn main() -> Result<(), Box<dyn std::error::Error>> {\n let path = Path::new(".");\n\n for entry in fs::read_dir(path)? {\n let entry = entry?;\n let path = entry.path();\n\n // जाँचें कि यह फ़ाइल है और एक्सटेंशन .rs है\n if path.is_file() && path.extension().map_or(false, |ext| ext == "rs") {\n println!("{}", path.display());\n }\n }\n\n Ok(())\n}\n\nmap_or का उपयोग सुरक्षित रूप से उस केस को संभालने के लिए ज़रूरी है जब फ़ाइल का कोई एक्सटेंशन न हो — path.extension() Option<&OsStr> लौटाता है।
3. रिकर्सिव ट्रैवर्सल: सभी सब-फ़ोल्डर में झाँकें
\n\nसाधारण read_dir सब-डायरेक्टरी में नहीं जाता। अगर आपको सभी फ़ाइलें रिकर्सिवली चाहिए (जैसे डुप्लीकेट खोजने के लिए), तो अपना रिकर्सिव फ़ंक्शन लिखना होगा। यह है एक सुंदर समाधान:
use std::fs;\nuse std::path::Path;\n\nfn visit_dirs(dir: &Path, depth: usize) -> Result<(), Box<dyn std::error::Error>> {\n if dir.is_dir() {\n for entry in fs::read_dir(dir)? {\n let entry = entry?;\n let path = entry.path();\n if path.is_dir() {\n visit_dirs(&path, depth + 1)?;\n } else {\n println!("{}", path.display());\n }\n }\n }\n Ok(())\n}\n\nfn main() -> Result<(), Box<dyn std::error::Error>> {\n visit_dirs(Path::new("."), 0)?;\n Ok(())\n}\n\nयह कैसे काम करता है?
\n- \n
visit_dirsफ़ंक्शन खुद को कॉल करता है जब उसे कोई सब-डायरेक्टरी मिलती है। \n depthपैरामीटर इंडेंटेशन के लिए है (आप चाहें तो इसे हटा सकते हैं)। \n - हर फ़ाइल का पथ प्रिंट होता है — चाहे वह कितनी भी गहराई में हो। \n
इसे चलाएँ और देखें कि आपके प्रोजेक्ट की सभी फ़ाइलें (जैसे src/main.rs, Cargo.toml, और .gitignore अगर है) लिस्ट हो जाती हैं।
4. एरर हैंडलिंग: क्या हो सकता है गलत?
\n\nRust में एरर हैंडलिंग अनिवार्य है। read_dir या visit_dirs में ये सामान्य एरर हो सकते हैं:
- \n
- डायरेक्टरी मौजूद नहीं —
No such file or directory\n - परमिशन नहीं —
Permission denied\n - सिमलिंक या स्पेशल फ़ाइल —
is_dir()गलत हो सकता है \n
हमारे कोड में ? ऑपरेटर एरर को तुरंत ऊपर भेज देता है। अगर आप एरर को इग्नोर करना चाहते हैं (जैसे परमिशन न होने पर), तो match या if let का उपयोग करें:
for entry in fs::read_dir(path)? {\n match entry {\n Ok(entry) => {\n let path = entry.path();\n if path.is_file() {\n println!("{}", path.display());\n }\n }\n Err(e) => eprintln!("एरर: {}", e), // एरर प्रिंट करें, लेकिन रुकें नहीं\n }\n}\n\n5. निष्कर्ष और अगले कदम
\n\nआपने सीखा:
\n- \n
std::fs::read_dirसे एक डायरेक्टरी की फ़ाइलें लिस्ट करना \n - एक्सटेंशन के अनुसार फ़िल्टर करना \n
- रिकर्सिव फ़ंक्शन से सभी सब-फ़ोल्डर ट्रैवर्स करना \n
- एरर को सुरक्षित रूप से हैंडल करना \n
अब आप इन तकनीकों का उपयोग करके अपना फ़ाइल मैनेजर, बैकअप टूल या लॉग एनालाइज़र बना सकते हैं। अगले ट्यूटोरियल में हम walkdir क्रेट का उपयोग करके और भी आसान रिकर्सिव ट्रैवर्सल देखेंगे। तब तक, अपने Rust प्रोजेक्ट में इसे आज़माएँ!