PHP DevCenter

oreilly.comSafari Books Online.Conferences.

We've expanded our LAMP news coverage and improved our search! Search for all things LAMP across O'Reilly!

Search
Search Tips

advertisement

Listen Print Discuss Subscribe to PHP Subscribe to Newsletters

PHP Foundations Working with Files in PHP, Part 3

by John Coggeshall
01/09/2003

Welcome back. In my last article I introduced how to use PHP to read and write binary files. This week, I'll introduce the concept of working with directories in PHP, including creating new directories, changing directories, and getting a file list for a given directory using PHP's pseudo directory object. We'll be starting from reading directories from a list, and then we'll discuss creating new directories or changing the current directory using PHP's directory manipulation functions. Let's get started.

The Directory Object

Working with directories in PHP is done through the use of a pre-defined pseudo object built internally into PHP called dir. This object has two member variables, $handle and $path, which represent the handle to the directory (for use in other functions) and the actual path of the directory (as a string). Along with these two variables, the dir object also has three member functions, read(), rewind(), and close().

Creating the Directory Object

Before we get into the specific member functions and their purposes, let's first take a look at how to create a directory object. Like any other object in PHP, instances are created with the new statement. In this case, when creating dir, it also needs a single parameter, which represents the directory being examined:

Related Reading

PHP Cookbook
By David Sklar, Adam Trachtenberg

<?php
   $mydir = dir('/path/to/mydir');
?>

Now that our directory class is created, the instance ($mydir) can be used in the same fashion as any other object. Our primary goal, of course, is to list all the files in the provided directory, so we'll start there.

Reading Files from the Directory Object

With the dir object created, let's take a look at its primary method: read(). This function reads one entry from the given directory at every call and returns it as a string, or the boolean value false if there are no more files to read. To use this function to read every file within a directory, simply use it within a while loop as follows. (We assume $mydir still exists.)

<?php
   while(($file = $mydir->read()) !== false) {
      echo "Filename: $file<BR>";
   }
?>

The above code fragment might look a bit strange, especially to the beginner developer and warrants a little extra explanation. Within the while statement above, a number of things are happening. First, we assign the result of the read() method call to the variable $file. Since that statement is enclosed within parenthesis, the value stored in $file is then used in the comparison for the while statement. Another oddity in the above fragment is the use of the !== operator (not equals, except with an additional equal sign). It's not a typo. This operator ensures that not only is a given value equal to (or in this case, not equal to) another value, but that they are also of the same variable type. Without this type of comparison, the while loop would end prematurely if a directory (or filename) existed with the name of false. In plain English, we read the current filename into $file, dropping out of the loop if there are no more files to read.

With all of the files in the given directory now displayed, the directory reference must be closed using the close() method. The entire example is shown below:

<?php
   $mydir = new dir('/path/to/mydir');
   while(($file = $mydir->read()) !== false) {
      echo "Filename: $file<BR>";
   }
   $mydir->close();
?>

You may have noticed that thus far we have not discussed any way of re-reading the contents of a directory without creating a new instance of the dir object. Thankfully, creating a new instance of the dir class is unnecessary. That's what the rewind() method is for. When this method is executed, the placeholder used to determine the next file in the directory listing is reset to the beginning, allowing you to re-access the file list as shown:

<?php
   $mydir = new dir('/path/to/mydir');
   while(($file = $mydir->read()) !== false) {
      echo "Filename: $file<BR>";
   }
   $mydir->rewind();
   echo "Displaying the directory list again...<BR>";
   while(($file = $mydir->read()) !== false) {
      echo "Filename: $file<BR>";
   }
   $mydir->close();

?>

Also in PHP Foundations:

Using MySQL from PHP, Part 2

Using MySQL from PHP

MySQL Crash Course, Part 3

MySQL Crash Course, Part 2

MySQL Crash Course

More Fun with Directories

Now that you know how to access the files within already existing directories, let's take a look at how to create new directories, change into existing ones, or determine if a given filename is a directory.

Determining If an Entry Is a Directory

In the examples I've shown you thus far, each entry returned from our example $mydir object was labeled as Filename in the output. Although acceptable for a simple demonstration, it is very likely (if not certain) that some of the entries are subdirectories, not files. To differentiate between the two, use the simple but useful function is_dir(). This function takes a single parameter (an absolute or relative pathname) and returns true if the path refers to a directory and false if it refers to a file.

Note: In case you are unsure what the difference between an "absolute" and "relative" pathname is, let me clarify. An absolute pathname is the complete path to the desired directory or file starting from the root of the filesystem. In UNIX-like systems, this would be something like /complete/path/to/file. Conversely, a relative pathname starts from the current directory (usually the same directory as the script being executed) and would be something like ../path/to/file.

Here's our previous example, modified to distinguish between entries returned:

<?php
   $mydir = new dir('/path/to/mydir');
   while(($file = $mydir->read()) !== false) {
      if(is_dir($mydir->path.$file)) {
         echo "Directory: $file<BR>";
      } else {
         echo "Filename: $file<BR>";
      }
   }
   $mydir->close();
?>

Notice that the complete path of the entry that we would like to check was provided to the is_dir() function. Without this, none of the entries would be processed properly since is_dir() would be looking only in the current directory, not necessarily the directory being read by $mydir object.

Changing the Current Directory

Of course, there are times when it would be useful to change the current directory in order to perform file manipulations, etc. In order to accomplish this, we'll use the PHP function chdir(). chdir() function takes a single parameter, the directory to change to, and returns either true or false indicating if PHP successfully changed into the desired directory.

Creating and Removing Directories

The last thing we'll discuss today is the creation and removal of directories from within PHP scripts. Both of these functions will only work properly on UNIX-like systems in directories that have write access granted for the user executing the PHP script (usually the Web server, i.e. nobody). Next time, I'll discuss file permissions in detail. For now just be aware of the limitation.

Creating a directory in PHP is done with the mkdir() function. This function takes two parameters as shown below:

mkdir($dir_to_create, $permission_mask);

$dir_to_create represents the absolute or relative path of the directory to create, and $permission_mask represents the permissions to give that directory. Since permissions won't be covered in detail until our next issue, we'll use 0777 (world-access) for our permission level and will create our directory in /tmp/, which is always available to everyone. Beware that this means that anyone with access to the system can both read and write to the files and directories we create.

<?php
   $result = mkdir('/tmp/mynewdir', 0777);
   if(!$result) {
      echo "Error: Couldn't create the directory!<BR>";

   } 
?>

Note: Regardless of the operating system PHP is running on, a permission mask is required in order for the function to work. Hence, if you are on a system where the permissions do not apply (such as Windows), simply use 0777 as your permission mask.

Likewise, directories can be removed using the PHP rmdir() function. This function takes a single parameter, the directory to remove, and returns a boolean value indicating if the function call succeeded:

<?php
   $result = rmdir('/tmp/mynewdir');
   if(!$result) {
      echo "Error: Couldn't remove the directory!<BR>";
   }
?>

Stay Tuned

That's it for today. Although I have touched on a few topics, which you may still be in the dark on (especially file permissions), don't worry. In my next article, I'll discuss permissions in detail that should clear up any problems that you might be having with them. Thanks for reading. See you next time.

John Coggeshall is a a PHP consultant and author who started losing sleep over PHP around five years ago.


Read more PHP Foundations columns.

Return to the PHP DevCenter.



Have any questions about the dir object? Post them here.
You must be logged in to the O'Reilly Network to post a talkback.
Post Comment
Full Threads Newest First

Showing messages 1 through 11 of 11.

  • dir class
    2003-02-06 12:31:15  arjo.post@hccnet.nl [Reply | View]

    the following object creation is not working for me:
    $mydir = new dir('/path/to/mydir');
    I get the error:
    Fatal error:
    Cannot instantiate non-existent class: dir in d:\myphp\dir.php on line 2
    can you help me?

    Thanks.
    Arjo
    • chromatic  photo dir class
      2003-02-12 10:48:17  chromatic | O'Reilly AuthorO'Reilly Blogger [Reply | View]

      It was a typo; it has since been fixed. (There is no need for the "new" keyword.)
    • dir class
      2003-11-19 12:28:21  anonymous2 [Reply | View]

      BTW, the if(is_dir($mydir->path.$file)) part includes the .. and . "directories"... so if, like me, you just wish to display a list of sub-directories, you'll need to ignore those two entries:

      if(is_dir($mydir->path.$file) && !strstr($file,".")) {

      Great article BTW :-)
      • dir class
        2005-02-09 11:43:32  poboxbot [Reply | View]

        Careful. Using strstr here will exclude all directories with a '.' character *anywhere* in its name.

        So while it will exclude "." and "..", it will also exclude "images.web" or "photos.icons" or whatever.

        Use preg_match instead:

        if(is_dir($path) && !preg_match("#^\.+#", $file))
    • dir class
      2004-11-05 18:22:58  Tyrrael [Reply | View]

      Its kind of simple, my guess its that it depends on PHP version, por PHP 4 just remove the creation of the class thats NEW
      from:
      $mydir = new dir('/path/to/mydir');

      to:
      $mydir = dir('/path/to/mydir');
  • line !== 'false'
    2003-03-12 15:22:26  anonymous2 [Reply | View]

    The article states that you need to use the !== comparison operator:
    "Without this type of comparison, the while loop would end prematurely if a directory (or filename) existed with the name of false"

    I can't seem to get the loop to stop when it encounters a directory named false even if I leave out the !== and use != instead.


    Using windows.
    • line !== 'false'
      2003-03-12 16:39:03  John Coggeshall | O'Reilly Author [Reply | View]

      Although this behavior may work (not using the 'identical' comparison and just using a standard comparison) it is not to be relied on. For instance:

      $myfile = "0"; // a filename whose name is '0'
      if($myfile == false) {
      echo "$myfile is false\n";
      } else {
      echo "$myfile is true.\n";
      }

      In this case, the string '0' will be evaluated as an integer value '0' which is in turn a boolean false. In order for this to behave properly you'd need to use the identical comparison === operator.

      John
      • line !== 'false'
        2005-03-17 10:11:01  Cerro [Reply | View]

        I was looking for some code to list the directory content with PHP3. The problem that i had was that i had a subdirectory named 0. Since in PHP3 there is no !== operator i did like this:

        function ListDir($dir)
        {
        if ((file_exists($dir)) && ($dh = opendir($dir)))
        {
        while (($file = readdir($dh)) || (((string) $file == "0") || ($file != false)))
        echo($file);
        closedir($dh);
        }
        }

        In this case the problem directory name is "0" but you can add "false" to the condition.



  • is_dir argument
    2003-03-25 14:51:50  anonymous2 [Reply | View]

    The line

    if(is_dir($mydir->path.$file)) {

    does not produce the desired effect for me; I changed it to

    if(is_dir("$mydir->path/$file")) {

    and it now works. Possibly a typo, or am I missing something? Would also probably work as

    if(is_dir($mydir->path.'/'.$file)) {

    if you wanted to keep it that way.
  • problem with read dir example
    2003-06-02 23:25:40  anonymous2 [Reply | View]

    Working with Files in PHP, Part Three -

    <?php
    $mydir = new dir('/path/to/mydir');
    while(($file = $mydir->read()) !== false) {
    if(is_dir($mydir->path.$file)) {
    echo "Directory: $file
    ";
    } else {
    echo "Filename: $file
    ";
    }
    }
    $mydir->close();
    ?>

    This doesn't work. You are concatenating the path with the filename, but skipped tacking on the trailing slash. perhaps some OS's leave the trailing slash and some do not (I really don't know), in which case, a test for a trailing slash as the last char with egrep might be in order.

    ddoman@panix.com
  • While loop args are incorrect
    2005-01-20 07:45:04  stevelux [Reply | View]

    couldn't get it to work so I consulted the PHP man.

    Where you have:

    while ($file = $mydir->read()) !== false)

    should be:

    while (false !== ($file = readdir($mydir)))

    That's what made it work for me. Please note that that I used:

    readdir()

    instead of:

    read()


Tagged Articles

Post to del.icio.us

This article has been tagged:

php

Articles that share the tag php:

Understanding MVC in PHP (477 tags)

The PHP Scalability Myth (123 tags)

The Dynamic Duo of PEAR::DB and Smarty (53 tags)

PHP Form Handling (43 tags)

Very Dynamic Web Interfaces (39 tags)

View All

programming

Articles that share the tag programming:

Rolling with Ruby on Rails (1374 tags)

Very Dynamic Web Interfaces (279 tags)

Ajax on Rails (231 tags)

Understanding MVC in PHP (202 tags)

A Simpler Ajax Path (186 tags)

View All

tutorials

Articles that share the tag tutorials:

Rolling with Ruby on Rails (178 tags)

From Weblog to CMS with WordPress (22 tags)

Top Ten Digital Photography Tips (16 tags)

A Simpler Ajax Path (16 tags)

Top Ten Mac OS X Tips for Unix Geeks (14 tags)

View All

directory

Articles that share the tag directory:

Building an Address Book with OpenLDAP (2 tags)

Working with Files in PHP, Part 3 (2 tags)

View All

Sponsored Resources

  • Inside Lightroom
Advertisement

Sponsored by:

O'Reilly Media

©2009, O'Reilly Media, Inc.
(707) 827-7000 / (800) 998-9938
All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.
About O'Reilly
Academic Solutions
Authors
Contacts
Customer Service
Jobs
Newsletters
O'Reilly Labs
Press Room
Privacy Policy
RSS Feeds
Terms of Service
User Groups
Writing for O'Reilly
Content Archive
Business Technology
Computer Technology
Google
Microsoft
Mobile
Network
Operating System
Digital Photography
Programming
Software
Web
Web Design
More O'Reilly Sites
O'Reilly Radar
Ignite
Tools of Change for Publishing
Digital Media
Inside iPhone
O'Reilly FYI
makezine.com
craftzine.com
hackszine.com
perl.com
xml.com

Partner Sites
InsideRIA
java.net
O'Reilly Insights on Forbes.com