2012-09-02 13 views
7

संभव डुप्लिकेट:
PHP SPL RecursiveDirectoryIterator RecursiveIteratorIterator retrieving the full treePHP फ़ोल्डर/सबफ़ोल्डर में सरणी में प्रत्येक फ़ाइल के लिए पथ मिलता है?

मुझे यकीन है कि जहां शुरू करने के लिए नहीं कर रहा हूँ। लेकिन मुझे एक फ़ोल्डर में सभी फ़ाइलों और पथों में उपफोल्डर की सभी सामग्री के पथ प्राप्त करना होगा। उदाहरण के लिए यदि मेरे पास 1 फ़ोल्डर था जिसमें पांच फ़ोल्डर्स थे और प्रत्येक फ़ोल्डर में 10 एमपी 3 थे ... इसका मतलब है कि मेरी सरणी को इन फ़ाइलों में 50 पथ मिलना होगा।

बाद में कहता है कि मैंने एक और फ़ोल्डर जोड़ा और इसमें 3 फ़ोल्डर्स थे और प्रत्येक फ़ोल्डर में 10 छवियां थीं।

मेरा कोड अब 80 पथ ढूंढने और उन्हें एक सरणी में स्टोर करने की आवश्यकता होगी।

क्या मेरा प्रश्न समझ में आता है?

अद्यतन:

मेरे बाहर वांछित डाल इन सभी एक सरणी में संग्रहीत रास्तों के लिए होगा।

लेकिन मैं कोड को गतिशील होने के लिए "प्यार" करता हूं, जिसका अर्थ है कि यदि मैं बाद में 10 और फ़ोल्डर जोड़ता हूं और प्रत्येक में 17 उपफोल्डर होते हैं और प्रत्येक फ़ोल्डर में विभिन्न सामग्री होती है। मैं सरणी को सभी फाइलों के फ़ाइल पथ को पकड़ना चाहता हूं। मैं समझता हूं यह समझ में आता है।

+1

मैं आपके पास फ़ोल्डर संरचना को समझता हूं। अब आप अपना आउटपुट क्या चाहते हैं। अपने प्रश्न में अपना ** वांछित आउटपुट ** अपडेट करें! :) –

+0

आप ऐसा क्यों करना चाहते हैं। मुझे PHP के साथ थोड़ा सा अनुभव है लेकिन मेरी राय में जो आपके खराब सर्वर को मार देगा। कल्पना करें कि 5000 लोग आपकी निर्देशिका संरचना के पठन कर रहे हैं !!! – Tanmay

+0

वैसे मैं ऐसा क्यों करना चाहता हूं क्योंकि मेरे पास Flash as3 में एक स्क्रिप्ट है जो एक समय में एक फ़ाइल डाउनलोड कर सकती है। फ्लैश एक फ़ोल्डर और इसकी सामग्री डाउनलोड नहीं कर सकता है, इसलिए मैं php को फ़ोल्डर्स/उपफोल्डर्स की सभी सामग्री की स्ट्रिंग बनाने और उसे वापस फ्लैश पर भेजना चाहता हूं और यह ऐप में सामग्री को डाउनलोड करना शुरू कर सकता है। :) –

उत्तर

23

क्या आप के लिए भी पुनरावर्ती निर्देशिका traversing कहा जाता है देख रहे हैं। जिसका अर्थ है, आप सभी निर्देशिकाओं और सूची उपनिर्देशिकाओं और फ़ाइलों में से जा रहे हैं। यदि कोई उपनिर्देशिका है तो यह भी आगे बढ़ती है और इतनी आगे और आगे भी - तो यह पुनरावर्ती है।

जैसा कि आप कल्पना कर सकते हैं कि यह एक सामान्य बात है जब आपको सॉफ़्टवेयर लिखते हैं और PHP आपको इसका समर्थन करता है। यह एक RecursiveDirectoryIterator प्रदान करता है ताकि निर्देशिका को फिर से घुमाया जा सके और ट्रैवर्सल करने के लिए मानक RecursiveIteratorIterator किया जा सके। फिर आप आसानी से सभी फ़ाइलों और निर्देशिकाओं एक सरल यात्रा के साथ, उदाहरण के लिए foreach के माध्यम से पहुँच सकते हैं:

$rootpath = '.'; 
$fileinfos = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($rootpath) 
); 
foreach($fileinfos as $pathname => $fileinfo) { 
    if (!$fileinfo->isFile()) continue; 
    var_dump($pathname); 
} 

सब से पहले यह उदाहरण निर्देशिका आप को पार करना चाहते हैं निर्दिष्ट करता है।मैं वर्तमान में ले जाने दिया गया है:

$rootpath = '.'; 

कोड की अगली पंक्ति में थोड़ा लंबा है, उसे the directory iterator का दृष्टांत है और फिर the iterator-iterator पेड़ की तरह संरचना एक एकल/फ्लैट पाश में चल जा सकता है ताकि :

$fileinfos = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($rootpath) 
); 

ये $fileinfos तो एक सरल foreach साथ दोहराया जाता है:

foreach($fileinfos as $pathname => $fileinfo) { 

अंदर इसके बारे में, सभी निर्देशिकाओं को आउटपुट होने से छोड़ने का एक परीक्षण है। यह SplFileInfo ऑब्जेक्ट का उपयोग करके किया जाता है जिसे पुन: चालू किया जाता है। यह रिकर्सिव डायरेक्टरी इटरेटर द्वारा प्रदान किया जाता है और फ़ाइलों के साथ काम करते समय बहुत उपयोगी गुण और विधियां होती हैं। उदाहरण के लिए आप फ़ाइल एक्सटेंशन, आकार और समय के बारे में बेसनाम जानकारी और इतने पर और आगे भी लौट सकते हैं।

if (!$fileinfo->isFile()) continue; 

अंत में मैं सिर्फ उत्पादन पथ नाम फ़ाइल का पूर्ण पथ है:

var_dump($pathname); 

एक अनुकरणीय निर्गम (एक विंडोज़ ऑपरेटिंग सिस्टम पर यहाँ) इस प्रकार दिखाई देगा:

string(12) ".\.buildpath" 
string(11) ".\.htaccess" 
string(33) ".\dom\xml-attacks\attacks-xml.php" 
string(38) ".\dom\xml-attacks\billion-laughs-2.xml" 
string(36) ".\dom\xml-attacks\billion-laughs.xml" 
string(40) ".\dom\xml-attacks\quadratic-blowup-2.xml" 
string(40) ".\dom\xml-attacks\quadratic-blowup-3.xml" 
string(38) ".\dom\xml-attacks\quadratic-blowup.xml" 
string(22) ".\dom\xmltree-dump.php" 
string(25) ".\dom\xpath-list-tags.php" 
string(22) ".\dom\xpath-search.php" 
string(27) ".\dom\xpath-text-search.php" 
string(29) ".\encrypt-decrypt\decrypt.php" 
string(29) ".\encrypt-decrypt\encrypt.php" 
string(26) ".\encrypt-decrypt\test.php" 
string(13) ".\favicon.ico" 

यदि कोई उपनिर्देशिका है जो पहुंच योग्य नहीं है, तो निम्न अपवाद फेंक देगा। जब RecursiveIteratorIterator instantiating यह व्यवहार कुछ झंडे के साथ नियंत्रित किया जा सकता:

$fileinfos = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator('.'), 
    RecursiveIteratorIterator::LEAVES_ONLY, 
    RecursiveIteratorIterator::CATCH_GET_CHILD 
); 

मुझे आशा है कि इस जानकारीपूर्ण गया था। आप इसे अपने आप में एक श्रेणी में भी लपेट सकते हैं और आप निर्णय लेने के लिए FilterIterator भी प्रदान कर सकते हैं कि फ़ाइल को सूचीबद्ध किया जाना चाहिए या foreach लूप से बाहर नहीं होना चाहिए।


RecursiveDirectoryIterator और RecursiveIteratorIterator संयोजन की शक्ति इसका लचीलापन से बाहर आता है। ऊपर जो कवर नहीं किया गया था उसे FilterIterator एस कहा जाता है। मैंने सोचा कि मैं एक और उदाहरण जोड़ता हूं जो उनमें से दो आत्म-लिखित रूपों का उपयोग कर रहा है, जो उन्हें गठबंधन करने के लिए एक-दूसरे में रखा गया है।

  • एक को फिल्टर करने की सभी फ़ाइलों और निर्देशिकाओं कि और
  • एक बिंदु के साथ शुरू करते हैं (उन यूनिक्स सिस्टम पर छिपी हुई फ़ाइलें माना जाता है ताकि आप बाहर करने के लिए है कि जानकारी नहीं देना चाहिए) एक और एक है कि फ़िल्टर कर रही है है केवल फाइलों की सूची। यही वह चेक है जो पहले फोरैच के अंदर था।

इस उपयोग का उदाहरण देखने में एक और परिवर्तन getSubPathname() function कि सब-पाथ यात्रा के rootpath से शुरू रिटर्न का उपयोग करना है, इसलिए एक आप देख रहे हैं।

इसके अलावा, मैं स्पष्ट रूप से SKIP_DOTS flag जो . और .. traversing रोकता जोड़ने (वास्तव में तकनीकी रूप से नहीं आवश्यक है क्योंकि फिल्टर उन के साथ-साथ वे निर्देशिका हैं फ़िल्टर कर जाएगा, फिर भी मुझे लगता है कि इसे और अधिक सही है) और UNIX_PATHS के रूप में पथ के रूप में वापसी

$rootpath = '.'; 

$fileinfos = new RecursiveIteratorIterator(
    new FilesOnlyFilter(
     new VisibleOnlyFilter(
      new RecursiveDirectoryIterator(
       $rootpath, 
       FilesystemIterator::SKIP_DOTS 
        | FilesystemIterator::UNIX_PATHS 
      ) 
     ) 
    ), 
    RecursiveIteratorIterator::LEAVES_ONLY, 
    RecursiveIteratorIterator::CATCH_GET_CHILD 
); 

foreach ($fileinfos as $pathname => $fileinfo) { 
    echo $fileinfos->getSubPathname(), "\n"; 
} 

यह उदाहरण पिछले के समान है: तो रास्तों में से तार अंतर्निहित ऑपरेटिंग सिस्टम सामान्य रूप से एक अच्छा विचार है कौन सा उन मूल्यों को बाद में अपने मामले में के रूप में HTTP के माध्यम से अनुरोध है कि वे अगर की परवाह किए बिना हमेशा यूनिक्स की तरह रास्ते हैं एक यद्यपिकैसेनिर्माण थोड़ा अलग कॉन्फ़िगर किया गया है। विशेष रूप से फिल्टर के बारे में हिस्सा नया है:

new FilesOnlyFilter(
     new VisibleOnlyFilter(
      new RecursiveDirectoryIterator($rootpath, ...) 
     ) 
    ), 

तो निर्देशिका इटरेटर एक फिल्टर में डाल दिया है और फिल्टर ही एक और फिल्टर में डाल दिया है। बाकी नहीं बदला।

कोड इन फिल्टर के लिए बहुत सीधे आगे है, वे accept समारोह है कि या तो true या false जो लेने के लिए या को फ़िल्टर करना है के साथ काम:

class VisibleOnlyFilter extends RecursiveFilterIterator 
{ 
    public function accept() 
    { 
     $fileName = $this->getInnerIterator()->current()->getFileName(); 
     $firstChar = $fileName[0]; 
     return $firstChar !== '.'; 
    } 
} 

class FilesOnlyFilter extends RecursiveFilterIterator 
{ 
    public function accept() 
    { 
     $iterator = $this->getInnerIterator(); 

     // allow traversal 
     if ($iterator->hasChildren()) { 
      return true; 
     } 

     // filter entries, only allow true files 
     return $iterator->current()->isFile(); 
    } 
} 

और वह इसे फिर से है। स्वाभाविक रूप से आप इन फिल्टरों को अन्य मामलों के लिए भी उपयोग कर सकते हैं। जैसे यदि आपके पास एक और प्रकार की निर्देशिका सूची है।

और $rootpath के साथ एक और अनुकरणीय उत्पादन दूर कटौती:

test.html 
test.rss 
tests/test-pad-2.php 
tests/test-pad-3.php 
tests/test-pad-4.php 
tests/test-pad-5.php 
tests/test-pad-6.php 
tests/test-pad.php 
TLD/PSL/C/dkim-regdom.c 
TLD/PSL/C/dkim-regdom.h 
TLD/PSL/C/Makefile 
TLD/PSL/C/punycode.pl 
TLD/PSL/C/test-dkim-regdom.c 
TLD/PSL/C/test-dkim-regdom.sh 
TLD/PSL/C/tld-canon.h 
TLD/PSL/generateEffectiveTLDs.php 

कोई और अधिक .git या .svn निर्देशिका ट्रावर्सल या .builtpath या .project की तरह फाइलों की सूची।


नोट FilesOnlyFilter और LEAVES_ONLY के लिए: फिल्टर स्पष्ट निर्देशिका और लिंक SplFileInfo वस्तु (only regular files that do exist) के आधार पर के उपयोग से इनकार करते हैं। तो यह फ़ाइल-सिस्टम के आधार पर एक असली फ़िल्टरिंग है।
डिफ़ॉल्ट LEAVES_ONLY flag (यहां उदाहरणों में भी उपयोग किया जाता है) के कारण RecursiveIteratorIterator के साथ गैर-निर्देशिका प्रविष्टियों के जहाजों को प्राप्त करने का एक और तरीका। यह ध्वज फ़िल्टर के रूप में काम नहीं करता है और अंतर्निहित पुनरावर्तक के लिए स्वतंत्र है। यह केवल निर्दिष्ट करता है कि पुनरावृत्ति शाखाओं को वापस नहीं करनी चाहिए (यहां निर्देशिका: निर्देशिका निर्देशिकाकर्ता के मामले में निर्देशिका)।

+0

अमेज़िंग! वाह! ठीक है, मैं केवल स्ट्रिंग (33) के बिना पथनाम कैसे प्राप्त करूंगा .. और मैं फ़ाइल नाम भी कैसे प्राप्त कर सकता हूं? :) –

+0

इसके अलावा पथ नाम शून्य से पहले/सही है? :) –

+0

इसे प्राप्त करने के कई तरीके हैं। आप 'foreach' के अंदर कुछ पोस्ट-प्रोसेसिंग के साथ "विस्तार" कर सकते हैं, ['SplFileInfo'] (http://php.net/SplFileInfo) ऑब्जेक्ट्स यहां सहायक हैं, आपके पास' $ fileinfo' में हैं। आधारित को हटाने के लिए वास्तव में मामूली है क्योंकि यह '$ रूटपाथ' है और फ़ाइल-सिस्टम निर्देशिका विभाजक है जो लंबाई आमतौर पर एक वर्ण है। तो आपके पास 'substr ($ pathname, 2) 'है। मैं एक और फिल्टर उदाहरण के साथ जवाब का विस्तार करूंगा और उस सबस्ट्रिंग ऑपरेशन को अनुकरणीय जोड़ दूंगा। – hakre

2

कदम जैसे:

और opendir निर्देशिका संरचना

$dh = opendir($dir)

खुल जाएगा कि क्या आप अगले पढ़ने के लिए है जो कुछ भी $dh

$file = readdir($dh)

में नहीं है आपसे संबंधित PHP मैनुअल में सभी जानकारी पा सकते हैं

और संरचना को पढ़ने के लिए googling लौटे इस

http://www.codingforums.com/showthread.php?t=71882

+0

बहुत बढ़िया। धन्यवाद। अच्छा लग रहा है। अब इसका परीक्षण कर रहा है :) आप वापस आ जाएगा। –

+0

कोई समस्या नहीं है। का आनंद लें! – Tanmay

+1

कुछ आसान के लिए अत्यधिक जटिल है, आप इसे कोड की 5 लाइनों (7 पठनीयता के लिए ब्रैकेट के साथ) में कर सकते हैं, आपको सटीक कोड के लिए नीचे अपना उत्तर देखें – RobertMaysJr

4

आप लिनक्स पर कर रहे हैं और आप एक शेल कमांड को क्रियान्वित करने से परहेज नहीं करते हैं, तो आप एक पंक्ति में कर सकते हैं

$path = '/etc/php5/*'; // file filter, you could specify a extension using *.ext 
$files = explode("\n", trim(`find -L $path`)); // -L follows symlinks 

print_r($files); 

आउटपुट:

Array (
     [0] => /etc/php5/apache2 
     [1] => /etc/php5/apache2/php.ini 
     [2] => /etc/php5/apache2/conf.d 
     [3] => /etc/php5/apache2/conf.d/gd.ini 
     [4] => /etc/php5/apache2/conf.d/curl.ini 
     [5] => /etc/php5/apache2/conf.d/mcrypt.ini 
     etc... 
    ) 

केवल PHP का उपयोग करने वाली अगली सबसे छोटी पसंद ग्लोब है- लेकिन यह उप-निर्देशिकाओं को स्कैन नहीं करती है जैसे कि आप चाहते हैं।(आप परिणामों के माध्यम से लूप करना होगा, का उपयोग is_dir() और फिर अपने समारोह

http://us3.php.net/glob

$files = dir_scan('/etc/php5/*'); 
print_r($files); 

function dir_scan($folder) { 
    $files = glob($folder); 
    foreach ($files as $f) { 
     if (is_dir($f)) { 
      $files = array_merge($files, dir_scan($f .'/*')); // scan subfolder 
     } 
    } 
    return $files; 
} 

फोन हर दूसरे रास्ते तो जिस तरह से अधिक कोड की आवश्यकता है आवश्यक होना चाहिए इतना आसान

कुछ करने के लिए
+0

पॉइंट नोट किया गया। धन्यवाद! – Tanmay

+1

:-) कोई समस्या नहीं। ग्लोब के बारे में एक और अच्छी बात यह है कि आप एक अलग फ़िल्टर (उदाहरण के लिए * .txt) निर्दिष्ट कर सकते हैं और एक ही समय में अपनी सभी फाइल फ़िल्टरिंग कर सकते हैं (न केवल एक्सटेंशन को जांचने के लिए आप प्रत्येक फ़ाइल नाम को पार्स करने से बचते हैं, आप नहीं करते यहां तक ​​कि उन पर लूप भी होना चाहिए क्योंकि वे पहले से ही फ़िल्टर किए गए हैं) – RobertMaysJr

+0

क्या प्रत्येक सरणी में इससे पहले/कम करने का कोई तरीका है? क्या मुझे कोई फ़ाइल और हो एक्सटेंशन के साथ फ़ाइल नामों की सरणी भी मिल सकती है? यह शानदार बीटीडब्ल्यू है। –

संबंधित मुद्दे