Does PHP get the path to each file in a folder / subfolder in an array?

Possible duplicate:
PHP SPL RecursiveDirectoryIterator RecursiveIteratorIterator restoring a full tree

I'm not sure where to start. But I also need to get the paths to all the files in the folder and the entire contents of the subfolder. For example, if I had 1 folder in which there were five folders, and each folder had 10 mp3 files in it, etc. This means that my array will have to find 50 paths to these files.

You can later say that I added another folder, and there were 3 folders in it, and each folder had 10 images.

Now my code should find 80 paths and store them in an array.

Does my question make sense?

UPDATE:

My desired element would be to have all of these paths be stored in one array.

But I would "LOVE" that the code be dynamic, that is, if I add 10 more folders later and each of which has 17 subfolders and each folder that has many different contents. I would like the array to contain the file paths of all files. I think that makes sense.

+7
source share
3 answers

What you are looking for is also called recursive directory migration. This means that you are viewing all directories and a list of subdirectories and files there. If there is a subdirectory, it also goes through, etc. Etc., therefore it is recursive.

As you can imagine, this is a pretty common thing that you need when you write software, and PHP supports you with that. It offers one RecursiveDirectoryIterator so that directories can be recursively repeated, and the standard RecursiveIteratorIterator for traversal. Then you can easily access all files and directories using a simple iteration, for example, through foreach :

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

This example primarily indicates the directory that you want to move. I accept the current:

 $rootpath = '.'; 

The following line of code is a little long, it creates an instance of the directory iterator , and then an iterator-iterator so that the tree structure can be moved in a single / flat outline:

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

These $fileinfos then repeated using a simple foreach :

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

There is a test inside it to skip all directories from the output. This is done using the SplFileInfo object, which is renamed. It is provided by a recursive directory iterator and contains many useful properties and methods when working with files. You can also return the file extension, database information about size and time, etc. Etc.

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

Finally, I just give the path, which is the full path to the file:

 var_dump($pathname); 

Sample output will look like this (here, on the Windows operating system):

 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" 

If there is a subdirectory that is not available, the following throws an exception. This behavior can be controlled with some flags when creating a RecursiveIteratorIterator :

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

Hope this was informative. You can also wrap this in your own class, and you can also provide a FilterIterator to move the decision about whether the file should be specified or not from the foreach .


The strength of the combination of RecursiveDirectoryIterator and RecursiveIteratorIterator goes beyond its flexibility. What has not been described above is called the so-called FilterIterator s. I thought I would add another example that uses two self-written ones placed in each other to combine them.

  • One of them is to filter out all files and directories starting with a period (this is considered hidden files on UNIX systems, so you should not transfer this information outside) and
  • Another that filters the list in files only. This is a check that was previously inside the foreach.

Another change in this use case is to use the getSubPathname() function, which returns a subpath starting from the root iteration path, so what you are looking for.

I also explicitly add the SKIP_DOTS flag, which prevents movement . and .. (technically not very necessary, because filters will filter them the same way they are directories, but I think this is more correct) and returned as UNIX_PATHS , so path strings are always unix-like paths, regardless on whether system is usually a good idea if these values ​​are requested via HTTP later, as in your case:

 $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"; } 

This example is similar to the previous one, although the build method for $fileinfos slightly different. Particularly important is the part about filters:

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

So, the directory iterator is placed in the filter, and the filter itself is placed in another filter. The rest has not changed.

The code for these filters is pretty simple, they work with the accept function, which is either true or false , which should accept or filter:

 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(); } } 

And that again. Naturally, you can use these filters for other cases. For example. if you have another directory listing.

And another example output with $rootpath disabled:

 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 

More .git or .svn directory traversal or list of files like .builtpath or .project .


Note for FilesOnlyFilter and LEAVES_ONLY : <Sub> The filter explicitly prohibits the use of directories and links based on the SplFileInfo object ( only ordinary files that exist ). So this is real file system filtering.
Another way to get only entries other than a directory with RecursiveIteratorIterator due to the standard LEAVES_ONLY flag (also used in the examples here). This flag does not work as a filter and does not depend on the main iterator. It simply indicates that the iteration should not return branches (here: directories in the case of a directory iterator).

+23
source

If you are working on Linux and you are not opposed to running a shell command, you can do it all on one line

 $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); 

Output:

 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... ) 

The next short choice using only PHP is glob- but it does not scan subdirectories as you want . (you will need to view the results, use is_dir (), and then call your function again

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; } 

Every other way requires more code, so you need to do something so simple.

+4
source

The steps as such:

and opendir will open the directory structure

$dh = opendir($dir)

what do you do next, read everything that is in $dh

$file = readdir($dh)

you can find all the information in the php directory matching opendir

and googling to read the structure returned it

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

+2
source

All Articles