PHP: Working with Directories

As is necessary for any language, PHP has a complete set of directory support functions. PHP gives you a variety of functions to read and manipulate directories and directory entries. Like other file-related parts of PHP, the functions are similar to the C functions that accomplish the same tasks, with some simplifications. This tutorial describes how PHP handles directories. You will look at how to create, remove, and read them.

Reading the Contents of a Directory

Let’s start with simple listing the contents of a directory. We need three functions to perform this task: opendir(), readdir() and closedir(). The opendir() function takes one parameter, which is the directory we want to read, and returns a directory handle to be used in subsequent readdir() and closedir() calls. opendir() returns False if the directory could not be opened.

The readdir() function takes one parameter, which is the handle that opendir() returned and each time we call readdir() it returns the filename of the next file in the directory. readdir() returns False if the end of the directory has been reached. Note that readdir() returns only the names of its items, rather than full paths.

The example below creates a select box that lists all the files in a directory. Copy and paste this code and save it as index.php in a directory you wish do display all files for. It automatically excludes itself from the list, and is easy to modify to make it ignore other files as well:

<?php
// open the current directory
$dhandle = opendir('.');
// define an array to hold the files
$files = array();

if ($dhandle) {
   // loop through all of the files
   while (false !== ($fname = readdir($dhandle))) {
      // if the file is not this file, and does not start with a '.' or '..',
      // then store it for later display

      if (($fname != '.') && ($fname != '..') &&
          ($fname != basename($_SERVER['PHP_SELF']))) {
          // store the filename
          $files[] = (is_dir( "./$fname" )) ? "(Dir) {$fname}" : $fname;
      }
   }
   // close the directory
   closedir($dhandle);
}

echo "<select name=\"file\">\n";
// Now loop through the files, echoing out a new select option for each one
foreach( $files as $fname )
{
   echo "<option>{$fname}</option>\n";
}
echo "</select>\n";
?>

First, we open the directory for reading with the opendir() function and use a while statement to loop through each of its entries. We call readdir() as part of the while statement’s test expression, assigning its result to the $fname variable. We are explicitly testing whether the return value is equal to and of the same type as False since otherwise, any directory entry whose name evaluates to False will stop the loop prematurely. Within the body of the while statement, we check if the file is not this file, and does not start with a . (current directory) or .. (parent directory) and then store the file name into the $files array. We also do one more check. If a full file path leads to a directory then we add to the file name “(Dir)”.

There is another way to iterate over all files in a directory. PHP 5 has a set of objects called iterators. Iterators help eliminate problems in your code. For instance, PHP 5 provides a DirectoryIterator:

<?php
echo "<select name=\"file\">\n";
foreach (new DirectoryIterator('.') as $file) {
   // if the file is not this file, and does not start with a '.' or '..',
   // then store it for later display

   if ( (!$file->isDot()) && ($file->getFilename() != basename($_SERVER['PHP_SELF'])) ) {
      echo "<option>";
      // if the element is a directory add to the file name "(Dir)"
      echo ($file->isDir()) ? "(Dir) ".$file->getFilename() : $file->getFilename();
      echo "</option>\n";
   }
}
echo "</select>\n";
?>

This example produces the same results as the earlier code that uses the directory functions, but this code is shorter and safer because you cannot forget the !== = comparison.

Back to top

Deleting the Directory and Its Contents

PHP has the rmdir( ) function that takes a directory name as its only parameter and will remove the specified directory from the file system, if the process running your script has the right to do so. However, the rmdir() function works only on empty directories. The example below deletes empty directory named “temporary”:

<?php
 rmdir( "temporary" );
?>

If you want to delete non-empty directory, you should use the recursion. In the following example we create recursive function named deleteDir() that takes a directory name as a parameter and will go through each subdirectory, deleting files as they go. When the directory is empty, we use rmdir() to remove it.

<?php
function deleteDir($dir) {
   // open the directory
   $dhandle = opendir($dir);

   if ($dhandle) {
      // loop through it
      while (false !== ($fname = readdir($dhandle))) {
         // if the element is a directory, and
         // does not start with a '.' or '..'
         // we call deleteDir function recursively
         // passing this element as a parameter

         if (is_dir( "{$dir}/{$fname}" )) {
            if (($fname != '.') && ($fname != '..')) {
               echo "<u>Deleting Files in the Directory</u>: {$dir}/{$fname} <br />";
               deleteDir("$dir/$fname");
            }
         // the element is a file, so we delete it
         } else {
            echo "Deleting File: {$dir}/{$fname} <br />";
            unlink("{$dir}/{$fname}");
         }
      }
      closedir($dhandle);
    }
   // now directory is empty, so we can use
   // the rmdir() function to delete it

   echo "<u>Deleting Directory</u>: {$dir} <br />";
   rmdir($dir);
}

// call deleteDir function and pass to it
// as a parameter a directory name
deleteDir("temporary");
?>

Another way to delete non-empty directory is to use RecursiveDirectoryIterator and RecursiveIteratorIterator. The RecursiveIteratorIterator must be told to provide children (files and subdirectories) before parents with its CHILD_FIRST constant. Have a look at the code:

<?php
function deleteDir($dir) {
   $iterator = new RecursiveDirectoryIterator($dir);
   foreach (new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::CHILD_FIRST) as $file)
   {
      if ($file->isDir()) {
         rmdir($file->getPathname());
      } else {
         unlink($file->getPathname());
      }
   }
   rmdir($dir);
}

deleteDir("temporary");
?>

Note: The CHILD_FIRST constant was added with PHP 5.1

Back to top

Creating New Directories

Creating new directories in PHP is accomplished using the mkdir() function, which takes two parameters. These parameters are, in order, a directory name you want to create and a permission mode for a new directory, which must be an octal number. The mode parameter is optional and has an effect only on Unix systems. Have a look at the example:

<?php
// if /path/to/my exists, this should return true
// if PHP has the right permissions

mkdir("/path/to/directory", 0777);
?>

By default, the mkdir() function only creates a directory if its parent exists. In PHP 5 the recursive parameter was added which should be true or false, depending on whether you want to create parent directories or not. In the following example, we pass true as a third parameter to mkdir(), so this makes the function act recursively to create any missing parent directories.

<?php
// will create /path/to/directory and
// also create /path and /path/to if needed and allowed
mkdir("/path/to/directory", 0777, true);
?>

Back to top

Related Articles

PHP: Looping Statements
 PHP: Functions

admin

admin

Leave a Reply

Your email address will not be published.