PHPRO.ORG

PHP SPL RecursiveDirectoryIterator Tutorial

PHP SPL RecursiveDirectoryIterator Tutorial

Contents

  1. SPL
  2. Recursive Directory Iterator
  3. Reflection
  4. Exceptions
  5. Recursing
  6. Filtering Dot Files
  7. isDot
  8. isDir
  9. Get File Last Access Time
  10. Get Inode Modification Time
  11. Get Group
  12. Get Inode
  13. Get Last Modification Time Of File
  14. Get File Owner
  15. Get File Path
  16. Get Path Name
  17. Get File Permissions
  18. Get File Size
  19. Get File Type
  20. Is Executable
  21. Is File
  22. Is Symbolic Link
  23. Is Readable
  24. Is Writable
  25. __toString
  26. Rewind
  27. Get Symbolic Link Target
  28. Get Real Path
  29. Filtering Recursive Directory Iterator
  30. Summary
  31. Credits

Recursive Directory Iterator

The recursiveDirectoryIterator is a member of the SPL suite of tools and provides an interface to recursively traverse a filesystem directory.

Reflection

A full breakdown can be seen with the available methods from the DirectoryIterator by using the reflection API like this:


<?php
    Reflection
::export(new ReflectionClass('recursiveDirectoryIterator'));
?>

Now we have a full list of available methods to the DirectoryIterator class. The list will look something like this:

Class [   class RecursiveDirectoryIterator extends FilesystemIterator implements Iterator, Traversable, SeekableIterator, RecursiveIterator ] {

  - Constants [12] {
    Constant [ public integer CURRENT_MODE_MASK ] { 240 }
    Constant [ public integer CURRENT_AS_PATHNAME ] { 32 }
    Constant [ public integer CURRENT_AS_FILEINFO ] { 0 }
    Constant [ public integer CURRENT_AS_SELF ] { 16 }
    Constant [ public integer KEY_MODE_MASK ] { 3840 }
    Constant [ public integer KEY_AS_PATHNAME ] { 0 }
    Constant [ public integer FOLLOW_SYMLINKS ] { 512 }
    Constant [ public integer KEY_AS_FILENAME ] { 256 }
    Constant [ public integer NEW_CURRENT_AND_KEY ] { 256 }
    Constant [ public integer OTHER_MODE_MASK ] { 12288 }
    Constant [ public integer SKIP_DOTS ] { 4096 }
    Constant [ public integer UNIX_PATHS ] { 8192 }
  }

  - Static properties [0] {
  }

  - Static methods [0] {
  }

  - Properties [0] {
  }

  - Methods [43] {
    Method [  public method __construct ] {

      - Parameters [2] {
        Parameter #0 [  $path ]
        Parameter #1 [  $flags ]
      }
    }

    Method [  public method hasChildren ] {

      - Parameters [1] {
        Parameter #0 [  $allow_links ]
      }
    }

    Method [  public method getChildren ] {

      - Parameters [0] {
      }
    }

    Method [  public method getSubPath ] {

      - Parameters [0] {
      }
    }

    Method [  public method getSubPathname ] {

      - Parameters [0] {
      }
    }

    Method [  public method rewind ] {

      - Parameters [0] {
      }
    }

    Method [  public method next ] {

      - Parameters [0] {
      }
    }

    Method [  public method key ] {

      - Parameters [0] {
      }
    }

    Method [  public method current ] {

      - Parameters [0] {
      }
    }

    Method [  public method getFlags ] {

      - Parameters [0] {
      }
    }

    Method [  public method setFlags ] {

      - Parameters [1] {
        Parameter #0 [  $flags ]
      }
    }

    Method [  public method getFilename ] {

      - Parameters [0] {
      }
    }

    Method [  public method getExtension ] {

      - Parameters [0] {
      }
    }

    Method [  public method getBasename ] {

      - Parameters [1] {
        Parameter #0 [  $suffix ]
      }
    }

    Method [  public method isDot ] {

      - Parameters [0] {
      }
    }

    Method [  public method valid ] {

      - Parameters [0] {
      }
    }

    Method [  public method seek ] {

      - Parameters [1] {
        Parameter #0 [  $position ]
      }
    }

    Method [  public method __toString ] {

      - Parameters [0] {
      }
    }

    Method [  public method getPath ] {

      - Parameters [0] {
      }
    }

    Method [  public method getPathname ] {

      - Parameters [0] {
      }
    }

    Method [  public method getPerms ] {

      - Parameters [0] {
      }
    }

    Method [  public method getInode ] {

      - Parameters [0] {
      }
    }

    Method [  public method getSize ] {

      - Parameters [0] {
      }
    }

    Method [  public method getOwner ] {

      - Parameters [0] {
      }
    }

    Method [  public method getGroup ] {

      - Parameters [0] {
      }
    }

    Method [  public method getATime ] {

      - Parameters [0] {
      }
    }

    Method [  public method getMTime ] {

      - Parameters [0] {
      }
    }

    Method [  public method getCTime ] {

      - Parameters [0] {
      }
    }

    Method [  public method getType ] {

      - Parameters [0] {
      }
    }

    Method [  public method isWritable ] {

      - Parameters [0] {
      }
    }

    Method [  public method isReadable ] {

      - Parameters [0] {
      }
    }

    Method [  public method isExecutable ] {

      - Parameters [0] {
      }
    }

    Method [  public method isFile ] {

      - Parameters [0] {
      }
    }

    Method [  public method isDir ] {

      - Parameters [0] {
      }
    }

    Method [  public method isLink ] {

      - Parameters [0] {
      }
    }

    Method [  public method getLinkTarget ] {

      - Parameters [0] {
      }
    }

    Method [  public method getRealPath ] {

      - Parameters [0] {
      }
    }

    Method [  public method getFileInfo ] {

      - Parameters [1] {
        Parameter #0 [  $class_name ]
      }
    }

    Method [  public method getPathInfo ] {

      - Parameters [1] {
        Parameter #0 [  $class_name ]
      }
    }

    Method [  public method openFile ] {

      - Parameters [3] {
        Parameter #0 [  $open_mode ]
        Parameter #1 [  $use_include_path ]
        Parameter #2 [  $context ]
      }
    }

    Method [  public method setFileClass ] {

      - Parameters [1] {
        Parameter #0 [  $class_name ]
      }
    }

    Method [  public method setInfoClass ] {

      - Parameters [1] {
        Parameter #0 [  $class_name ]
      }
    }

    Method [  final public method _bad_state_ex ] {
    }
  }
}

Using the listed methods from the above code allows us to see how much information we can get from the class. The reflection API allows us to see inside the DirectoryIterator class so that each of the methods is displayed along with the class it inherits from. Lets go over it.

Exceptions

The constructor takes an directory path as its arguement. The directory must be a valid directory that is readable by the process. If the directory does not exist, or cannot be accessed, an exception is thrown as shown here.


<?php
    $it 
= new recursiveDirectoryIterator('/does_not_exist');
?>

The code above will produce an fatal error due to an un-caught exception like this:

PHP Fatal error:  Uncaught exception 'UnexpectedValueException' with message 'RecursiveDirectoryIterator::__construct(/does_not_exist): failed to open dir: No such file or directory' in /phpro.org/it.php:2
Stack trace:
#0 /phpro.org/it.php(2): RecursiveDirectoryIterator->__construct('/does_not_exist')
##1 {main}
#  thrown in /phpro.org/it.php on line 2
#
#  Fatal error: Uncaught exception 'UnexpectedValueException' with message 'RecursiveDirectoryIterator::__construct(/does_not_exist): failed to open dir: No such file or directory' in /phpro.org/it.php:2
#  Stack trace:
#  #0 /phpro.org/it.php(2): RecursiveDirectoryIterator->__construct('/does_not_exist')
#  #1 {main}
#    thrown in /phpro.org/it.php on line 2
#

Because of this, it is important to catch and handle any exceptions. Here a simple try/catch is used to handle the exception and display the error.


<?php
    
try
    {
        
/*** specify a non-existant directory ***/
        
$it = new recursiveDirectoryIterator('/does_not_exist');
    }
    catch(
Exception $e)
    {
        
/*** echo the error message ***/
        
echo $e->getMessage();
    }
?>

Now that the exception has been caught, the error message is echo'ed in the catch block

RecursiveDirectoryIterator::__construct(/does_not_exist): failed to open dir: No such file or directory

Of course, in a production environment, the exception would need to be handled in such a way as system error messages were not displayed to the user.

Recursing

Lets create directory tree in /home/fred

/home/fred
    one.html
    two.html
    sub1
        sub2
        one.html
        two.html

We can now use the recursiveDirectoryIterator to traverse the directory as see here:


<?php
try
{
        
/*** freds home directory ***/
        
$it = new recursiveDirectoryIterator('/home/fred');
        while( 
$it->valid())
        {
                echo 
$it->getSubPathName() . $it->key() . "\n";

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>    

And the results look like this

sub1/home/fred/sub1
../home/fred/..
one.html/home/fred/one.html
two.html/home/fred/two.html
./home/fred/.

WTF! Why did the it not recurse and only show the first level?

To see the recursiveDirectoryIterator recurse, we need an recursive iterator, to iterate over the recursiveDirectoryIterator iterator. The tool to do this is the recursiveIteratorIterator iterator. Here we see the use of the recursiveIteratorIterator which takes the recursiveDirectoryIterator iterator as its single arguement.


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred');
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                echo 
$it->getSubPathName() . $it->key() . "\n";

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

Now the results show the entire structure of the directory

sub1/home/fred/sub1
sub1/sub2/sub_two.html/home/fred/sub1/sub2/sub_two.html
sub1/sub2/../home/fred/sub1/sub2/..
sub1/sub2/./home/fred/sub1/sub2/.
sub1/sub2/sub_one.html/home/fred/sub1/sub2/sub_one.html
sub1/../home/fred/sub1/..
sub1/./home/fred/sub1/.
../home/fred/..
one.html/home/fred/one.html
two.html/home/fred/two.html
./home/fred/.

Filtering Dot Files

The results shown above have correctly displayed the contents of the /home/fred directory. However, the dot file . and .. are displayed also. These can be filtered out with the isDot() method which is included in the recursiveDirectoryIterator iterator.

isDot

Note also in the two above examples, all the files are displayed, including directories and even hidden files. Moving further into the list of methods displayed from reflection, the isDot() and isDir() methods are provided to deal with exactly this situation.


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred');
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( !
$it->isDot() )
                {
                        echo 
$it->key() . "\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>
/home/fred/sub1
/home/fred/sub1/sub2/sub_two.html
/home/fred/sub1/sub2/sub_one.html
/home/fred/one.html
/home/fred/two.html

Now the the results change a little by the removal of the . and .. directories that point to the current directory and the parent directory. Note that the isDot() method only refers to the. and .. directories and not to hidden files.

The same result could be achieved passing some arguments to the recursiveDirectoryIterator iterator.


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                echo 
$it->key() . "\n";

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

isDir

The isDir() method works in much the same fashion. This method returns true if the current iteration is a directory. Now it is simple to filter out the directories from the listing.


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( !
$it->isDir() )
                {
                        echo 
$it->key() . "\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

With the isDir() method in place, the results now change to omit any sub directories that may be within the directory that is being iterated over.

home/fred/sub1/sub2/sub_two.html
/home/fred/sub1/sub2/sub_one.html
/home/fred/one.html
/home/fred/two.html

Get File Last Access Time

Even further into the results from the reflection results, is a vast number of methods provided by the SPLFileInfo class which the recursiveDirectoryIterator also extends from. Demonstrating each of these methods would be insane, but in these troubled times, who is to say that insane solutions are not the answer?!


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( !
$it->isDir() )
                {
                        echo 
$it->current().' '.date('Y m d H:i:s'$it->getATime() )."\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/sub1/sub2/sub_two.html 2014 05 30 05:50:11
/home/fred/sub1/sub2/sub_one.html 2014 05 30 05:50:06
/home/fred/one.html 2014 05 30 05:49:31
/home/fred/two.html 2014 05 30 05:49:36

Get Inode Modification Time


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( !
$it->isDir() )
                {
                        echo 
$it->current().' '.date('Y m d H:i:s'$it->getCTime() )."\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

Get Group


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( !
$it->isDir() )
                {
                        echo 
$it->current().' '$it->getCTime() . "\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/sub1/sub2/sub_two.html 1401393011
/home/fred/sub1/sub2/sub_one.html 1401393006
/home/fred/one.html 1401392971
/home/fred/two.html 1401392976

Get Inode


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( !
$it->isDir() )
                {
                        echo 
$it->current().' '$it->getInode() . "\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/sub1/sub2/sub_two.html 50596688
/home/fred/sub1/sub2/sub_one.html 50596687
/home/fred/one.html 50596683
/home/fred/two.html 50596684

Get Last Modification Time Of File


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( !
$it->isDir() )
                {
                        echo 
$it->current().' '$it->getMTime() . "\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/sub1/sub2/sub_two.html 1401393011
/home/fred/sub1/sub2/sub_one.html 1401393006
/home/fred/one.html 1401392971
/home/fred/two.html 1401392976

Get File Owner


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( !
$it->isDir() )
                {
                        echo 
$it->current().' '$it->getOwner() . "\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/sub1/sub2/sub_two.html 500
/home/fred/sub1/sub2/sub_one.html 500
/home/fred/one.html 500
/home/fred/two.html 500

Get File Path


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( !
$it->isDir() )
                {
                        echo 
$it->getPath()."\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/sub1/sub2
/home/fred/sub1/sub2
/home/fred
/home/fred

Get Path Name

The above functions uses a joining of the path and the current filename within the iterator to fetch the file path and filename. The getPathName() method does this all in one go.


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( !
$it->isDir() )
                {
                        echo 
$it->getPathName()."\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>
/home/fred/sub1/sub2/sub_two.html
/home/fred/sub1/sub2/sub_one.html
/home/fred/one.html
/home/fred/two.html

Get File Permissions


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( !
$it->isDir() )
                {
                        echo 
$it->current().' '$it->getPerms()."\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/sub1/sub2/sub_two.html 33204
/home/fred/sub1/sub2/sub_one.html 33204
/home/fred/one.html 33204
/home/fred/two.html 33204

Get File Size


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( !
$it->isDir() )
                {
                        echo 
$it->current().' '$it->getSize()."\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/sub1/sub2/sub_two.html 103
/home/fred/sub1/sub2/sub_one.html 12
/home/fred/one.html 38
/home/fred/two.html 12

Get File Type


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( !
$it->isDir() )
                {
                        echo 
$it->current().' '$it->getType()."\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/sub1/sub2/sub_two.html file
/home/fred/sub1/sub2/sub_one.html file
/home/fred/one.html file
/home/fred/two.html file

Is Executable


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( !
$it->isDir() )
                {
                                if( 
$it->isExecutable() )
                                {
                                        echo 
$it->current()." is executable \n";
                                }
                                else
                                {
                                        echo 
$it->current()." is not executable \n";
                                }
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/sub1/sub2/sub_two.html is not executable 
/home/fred/sub1/sub2/sub_one.html is not executable 
/home/fred/one.html is not executable 
/home/fred/two.html is not executable

Is File


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( 
$it->isFile() )
                {
                        echo 
$it->current()."\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/sub1/sub2/sub_two.html
/home/fred/sub1/sub2/sub_one.html
/home/fred/one.html
/home/fred/two.html

Is Symbolic Link

For this example, a symbolic link has been created.


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( 
$it->isLink() )
                {
                        echo 
$it->current()."\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/three.html

Is Readable


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( 
$it->isFile() && $it->isReadable() )
                {
                        echo 
$it->current()."\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

?>
/home/fred/sub1/sub2/sub_two.html
/home/fred/sub1/sub2/sub_one.html
/home/fred/one.html
/home/fred/two.html
/home/fred/three.html

Is Writable

Check If File Is Writable

For this demonstration, the /home/fred/two.html. file has been set to writable using

chmod a+w /home/fred/two.html

<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( 
$it->isFile() && $it->isWritable() )
                {
                        echo 
$it->current()."\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/sub1/sub2/sub_two.html
/home/fred/sub1/sub2/sub_one.html
/home/fred/one.html
/home/fred/two.html
/home/fred/three.html

__toString

__toString

The directoryIterator __toString() method is simply and alias of getPathname.


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( 
$it->isFile() )
                {
                        echo 
$it->__toString()."\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>
sub_two.html
sub_one.html
one.html
two.html
three.html

Rewind

As the name suggests, this method will rewind to the beginning of the iteration object.


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                if( 
$it->isFile() )
                {
                        echo 
$it->__toString()."\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }

        
// rewind
        
$it->rewind();

        echo 
$it->current();
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

sub_two.html
sub_one.html
one.html
two.html
three.html
/home/fred/sub1/sub2/sub_two.html

Get Link Target

Fetches the target path and filename of a symbolic link


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                       
/*** check if element is a file ***/
                        
if( $it->isLink() )
                        {
                                echo 
$it->getLinkTarget()."\n";
                        }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/one.html

Get Real Path


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                        
/*** check if element is a file ***/
                        
if( $it->isFile() )
                        {
                                
/*** fetche the real path ***/
                                
echo $it->getRealPath()."\n";
                        }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/sub1/sub2/sub_two.html
/home/fred/sub1/sub2/sub_one.html
/home/fred/one.html
/home/fred/two.html
/home/fred/one.html

Filtering Recursive Directory Iterator

We have seen previously using if statements to filter out directories and other filtering techniques. However, if the need is for many filters, this will get quite cumbersome. Introducing the FilterIterator to do the filtering for us, and create a re-usable filter. For this example, a file named four.php has been added to /home/fred.

To do this a class is created which extends the filterIterator class. By utilizing the accept method, only the files with a .php extention can be returned, and all other files filtered out. Other filters can be put in the accept method, have a play and create your own.

The class itself looks like this:


<?php

try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred');
        
$rii = new recursiveIteratorIterator$rdi );
        
$it = new phproFilter$rii );
        while( 
$it->valid())
        {
                
/*** check if element is a file ***/
                
if( $it->isFile() )
                {
                        
/*** fetche the real path ***/
                        
echo $it->getRealPath()."\n";
                }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}


/** class to filter out all but .php files ***/
class phproFilter extends FilterIterator
{
        
/**
         * Create an instance of the locater iterator
         * 
         * @param  recursiveIteratorIterator $iterator 
         * @return void
         */
        
public function __constructrecursiveIteratorIterator $iterator )
        {
                
parent::__construct($iterator);
                
$this->rewind();
        }

        
/**
         * Filter to return only files with .php extension
         * 
         * @return bool
         */
        
public function accept()
        {
                
$file $this->getInnerIterator()->current();

                
/*** Filter out anything but files ***/
                
if (!$file->isFile()) {
                        return 
false;
                }

                
// If not a PHP file, skip
                
if ($file->getBasename('.php') == $file->getBasename()) {
                        return 
false;
                }
                
// No class-type tokens found; return false
                
return true;
        }
}


<?php
try
{
        
/*** freds home directory ***/
        
$rdi = new recursiveDirectoryIterator('/home/fred',  FilesystemIterator::SKIP_DOTS FilesystemIterator::UNIX_PATHS);
        
$it = new recursiveIteratorIterator$rdi );
        while( 
$it->valid())
        {
                        
/*** check if element is a file ***/
                        
if( $it->isFile() )
                        {
                                
/*** fetche the real path ***/
                                
echo $it->getRealPath()."\n";
                        }

                
/*** move to the next element ***/
                
$it->next();
        }
}
catch(
Exception $e)
{
        
/*** echo the error message ***/
        
echo $e->getMessage();
}
?>

/home/fred/sub1/sub2/sub_two.html
/home/fred/sub1/sub2/sub_one.html
/home/fred/one.html
/home/fred/two.html
/home/fred/one.html

Summary

This tutorial has shown how dealing with directory structures is made more efficient within an Object Oriented framework. SPL iterators provide this same functionality for all aggregate structures, regardless of type.

Credits

Many thanks to Marcus Boerger for his help with the code in this tutorial and quick fixes to bugs in the PHP 5.1.0 core as we came across them. Marcus is a PHP core developer and the creator of SPL.