Skip to main content

A few handy PHP functions for dealing with the file system. Delete directories, read/write files, etc. Also, PHP apparently doesn't have a native delete directory recursively method (that I know of), so I included one I found.

<?php

/**
 * Create a directory
 *
 * @param  string  $path  The full path of the dir to create.
 * @return boolean        Returns true if the directory was created. False if it already exists or oper. failed.
 */
function create_dir($path)
{
    if (! is_dir($path))
    {
        return mkdir($path);
    }
    else
    {
        return false; // dir already exists.
    }
}

/**
 * Moves a file or directory to a new location.
 *
 * @param $src string
 *            Source path of file/dir to move.
 * @param $dest string
 *            Destination path.
 * @return bool Returns true if successful.
 */
function move($src, $dest)
{
    if (file_exists($src))
    {
        return rename($src, $dest);
    }
    else
    {
        return false;
    }
}

/**
 * Delete directory recursively
 *
 * This PHP function scans a given directory and deletes all files and
 * subdirectories it finds and has permission to delete.
 *
 * Per default it removes the given directory totally, but you can
 * specify to just "empty" it instead. In this case it deletes
 * everything inside the given directory and keeps the directory itself.
 *
 * @param $directory string
 *            The path to directory.
 * @param $empty bool
 *            Set to true to leave the directory in tact, but empty all it's contents.
 * @return boolean
 *
 * @author http://lixlpixel.org/recursive_function/php/recursive_directory_delete/
 */
function remove_dir($directory, $empty = false)
{
    if (substr($directory, - 1) == '/')
    { // remove appending slashes
        $directory = substr($directory, 0, - 1);
    }

    if (! file_exists($directory) || ! is_dir($directory))
    {
        return false;
    }
    elseif (! is_readable($directory))
    {
        return false;
    }
    else
    {

        $handle = opendir($directory);

        while (false !== ($item = readdir($handle)))
        {

            if ($item != '.' && $item != '..')
            {
                $path = $directory . '/' . $item;

                if (is_dir($path))
                {
                    remove_dir($path);
                }
                else
                {
                    unlink($path);
                }
            }
        }

        closedir($handle);

        // if the option to empty is not set to true
        if ($empty === false)
        {
            if (! rmdir($directory))
            {
                return false;
            }
        }

        return true;
    }
}

/**
 * Recursive copy
 *
 * I had to copy a directory but the top level folder name would be different
 * at dest i.e. dirparent/dirchild -> diff/dirchild . I thought I would just
 * copy and rename the destination but you can't rename non empty directories.
 * This function as a workaround.
 *
 * @param string $source
 *            Source file path.
 * @param string $dest
 *            Destination file path.
 * @param string $ds
 *            Directory seperator.
 * @return bool True on success.
 *
 * @author http://us2.php.net/manual/en/function.copy.php#104809 (slightly modified - jon labelle)
 */
function copy_recursive($source, $dest, $ds = '/')
{
    if (! $dir = opendir($source))
    {
        return false;
        // fwrite(STEDRR, 'ERROR: Unable to open ' . $source . "\n");
        // exit(1);
    }

    if (! is_dir($dest))
    {
        if (mkdir($dest) === false)
        {
            return false; // failed to make dest dir
        }
    }

    while ($file = readdir($dir))
    {

        if ($file != '.' && $file != '..')
        {
            $path = $source . $ds . $file;

            // create directory and copy contents
            if (is_dir($path))
            {
                copy_recursive($path, $dest . $ds . $file);
            }
            else
                if (is_file($path))
                {
                    if (! copy($path, $dest . $ds . $file))
                    {
                        return false;
                        // fwrite(STDERR, 'ERROR: Unable to copy file ' . $file . '.' . "\n");
                        // exit(1);
                    }
                }
        }
    }
    closedir($dir);

    return true;
}

/**
 * Get file info
 *
 * Given a file and path, returns the name, path, size, date modified Second
 * parameter allows you to explicitly declare what information you want returned
 * Options are: name, server_path, size, date, readable, writable, executable,
 * fileperms Returns FALSE if the file cannot be found.
 *
 * @param string $file
 *            Path to file.
 * @param mixed $returned_values
 *            Array or comma separated string of information returned.
 * @param string $ds
 *            Directory seperator. The default is a forward-slash.
 * @return mixed Returns false if the file does not exist, otherwise an array with the file information.
 *
 * @author from CodeIgniter's core file_helper.php.
 */
function get_file_info($file, $returned_values = array('name', 'server_path', 'size', 'date'), $ds = '/')
{
    if (! file_exists($file))
    {
        return false;
    }

    if (is_string($returned_values))
    {
        $returned_values = explode(',', $returned_values);
    }

    foreach ($returned_values as $key)
    {
        switch ($key)
            {
                case 'name':
                    $fileinfo['name'] = substr(strrchr($file, $ds), 1);
                    break;
                case 'server_path':
                    $fileinfo['server_path'] = $file;
                    break;
                case 'size':
                    $fileinfo['size'] = filesize($file);
                    break;
                case 'date':
                    $fileinfo['date'] = filemtime($file);
                    break;
                case 'readable':
                    $fileinfo['readable'] = is_readable($file);
                    break;
                case 'writable':
                    // There are known problems using is_weritable on IIS. It may not be reliable - consider fileperms()
                    $fileinfo['writable'] = is_writable($file);
                    break;
                case 'executable':
                    $fileinfo['executable'] = is_executable($file);
                    break;
                case 'fileperms':
                    $fileinfo['fileperms'] = fileperms($file);
                    break;
            }
    }

    return $fileinfo;
}

/**
 * Get directory file information
 *
 * Reads the specified directory and builds an array containing
 * the filenames, filesize, dates, and permissions. Any sub-folders
 * contained within the specified path are read as well.
 *
 * @param string $source_dir
 *            Path to source
 * @param bool $top_level_only
 *            Look only at the top level directory specified?
 * @param bool $_recursion
 *            Internal variable to determine recursion status - do not use in calls
 * @return array boolean
 * @author from CodeIgniter's core file_helper.php.
 */
function get_dir_file_info($source_dir, $top_level_only = true, $_recursion = false, $ds = '/')
{
    $_filedata = array();
    $relative_path = $source_dir;

    if ($fp = @opendir($source_dir))
    {
        // reset the array and make sure $source_dir has a trailing slash on the initial call
        if ($_recursion === false)
        {
            $_filedata = array();
            $source_dir = rtrim(realpath($source_dir), $ds) . $ds;
        }

        // foreach (scandir($source_dir, 1) as $file) // In addition to being PHP5+, scandir() is simply not as fast
        while (true !== ($file = readdir($fp)))
        {

            if (@is_dir($source_dir . $file) && $file[0] !== '.' && $top_level_only === false)
            {
                get_dir_file_info($source_dir . $file . $ds, $top_level_only, true);
            }
            elseif ($file[0] !== '.')
            {
                $_filedata[$file] = get_file_info($source_dir . $file);
                $_filedata[$file]['relative_path'] = $relative_path;
            }
        }

        closedir($fp);

        return $_filedata;
    }

    return FALSE;
}

/**
 * Delete a file.
 *
 * @param string $file
 *            The complete path to file.
 */
function delete_file($file)
{
    if (file_exists($file))
    {
        unlink($file);
    }
}

/**
 * Reads the content of the file into a string.
 *
 * @param string $file
 *            The complete file path.
 * @return string
 */
function read_file($file)
{
    $contents = '';

    if (file_exists($file))
    {

        if (function_exists('file_get_contents'))
        {
            return file_get_contents($file);
        }

        $fh = fopen($file, "r");
        $contents = fread($fh, filesize($file));
        fclose($fh);
    }

    return $contents;
}

/**
 * Write File
 *
 * Writes data to the file specified in the path. Creates a new
 * file if non-existent.
 *
 * @param string $path
 *            Path to file
 * @param string $date
 *            Data to write to the file.
 * @param int $mode
 *            The type of access you require for the stream. The default mode truncates existing file data.
 *
 * @author from CodeIgniter's core file_helper.php.
 */
function write_file($path, $data, $mode = 'wb')
{
    if (! $fp = @fopen($path, $mode))
    {
        return false;
    }

    flock($fp, LOCK_EX); // acquire an exclusive lock (writer).
    fwrite($fp, $data);
    flock($fp, LOCK_UN); // release the lock
    fclose($fp);

    return true;
}

/**
 * Gets the file extensions.
 *
 * @param string $file
 *            The file.
 * @return string Returns the file extension.
 */
function get_file_extension($file)
{
    return strtolower(substr(strrchr($file, "."), 1));
}