PHP Folder and File Copy/Move Operations


Learn how to efficiently manage files in PHP by utilizing built-in functions to copy and move files. This tutorial includes detailed explanations and examples for practical usage.

How to Copy Files Using PHP

The copy() function in PHP allows you to duplicate files from one location to another. Below is a simple example:

PHP
<?php
$sourceFile = '/path/to/source.txt';
$destinationFile = '/path/to/destination.txt';

if (copy($sourceFile, $destinationFile)) {
    echo "File copied successfully!";
} else {
    echo "Failed to copy file.";
}
?>

How to Move Files Using PHP

To move files, PHP provides the rename() function. This can be used to move a file to a new location or rename it. Here's an example:

PHP
<?php
$oldPath = '/path/to/old_location.txt';
$newPath = '/path/to/new_location.txt';

if (rename($oldPath, $newPath)) {
    echo "File moved successfully!";
} else {
    echo "Failed to move file.";
}
?>

How to Copy All Files in a Folder Using PHP

The copyFolderContents function is a versatile and efficient utility designed to copy the contents of a source folder to a destination folder, with optional recursive copying of sub directories. It incorporates robust error handling to ensure reliability, providing detailed feedback on successes and failures during the operation. The function automatically creates destination directories if they don't exist, normalizes file paths for consistency, and ensures compatibility across different operating systems.

The following code demonstrates how to copy all files from one folder to another:

PHP
<?php
/**
 * Enhanced folder and file copying function with an overwrite option.
 *
 * @param string $source Source directory path
 * @param string $destination Destination directory path
 * @param bool $recursive Whether to copy subdirectories recursively
 * @param bool $overwrite Whether to overwrite existing files in the destination
 * @return array Operation results with success and error details
 */
function copyFolderContents(string $source, string $destination, bool $recursive = true, bool $overwrite = true): array {
    // Normalize paths to remove trailing slashes
    $source = rtrim($source, '/\\');
    $destination = rtrim($destination, '/\\');

    // Initialize results tracking
    $results = [
        'success' => true,
        'error' => null,
        'copied_files' => [],
        'failed_files' => []
    ];

    // Validate source directory
    if (!is_dir($source)) {
        $results['success'] = false;
        $results['error'] = "Source folder does not exist or is not a directory: $source";
        return $results;
    }

    // Create destination folder if it doesn't exist
    if (!file_exists($destination) && !mkdir($destination, 0755, true)) {
        $results['success'] = false;
        $results['error'] = "Cannot create destination folder: $destination";
        return $results;
    }

    // Ensure destination is a valid directory
    if (!is_dir($destination)) {
        $results['success'] = false;
        $results['error'] = "Destination is not a valid directory: $destination";
        return $results;
    }

    // Read contents of the source directory
    $items = scandir($source);
    if ($items === false) {
        $results['success'] = false;
        $results['error'] = "Failed to read source folder: $source";
        return $results;
    }

    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }

        $sourceItem = $source . DIRECTORY_SEPARATOR . $item;
        $destinationItem = $destination . DIRECTORY_SEPARATOR . $item;

        // Handle files
        if (is_file($sourceItem)) {
            if (!$overwrite && file_exists($destinationItem)) {
                // Skip overwriting the existing file
                $results['failed_files'][] = $destinationItem; // Track skipped files
                continue;
            }

            // Copy file and track the result
            if (@copy($sourceItem, $destinationItem)) {
                $results['copied_files'][] = $destinationItem;
            } else {
                $results['failed_files'][] = $sourceItem;
                $results['success'] = false;
            }
        }

        // Handle directories recursively
        elseif ($recursive && is_dir($sourceItem)) {
            $subResults = copyFolderContents($sourceItem, $destinationItem, true, $overwrite);

            // Merge results from subdirectories
            $results['copied_files'] = array_merge($results['copied_files'], $subResults['copied_files']);
            $results['failed_files'] = array_merge($results['failed_files'], $subResults['failed_files']);
            if (!$subResults['success']) {
                $results['success'] = false;
            }
        }
    }

    return $results;
}
?>

Usage Copy Function

PHP
<?php
// Example usage
$sourceFolder = '/path/to/source/folder';
$destinationFolder = '/path/to/destination/folder';
$overwrite = false; // Set to true to enable overwriting files

$copyResults = copyFolderContents($sourceFolder, $destinationFolder, true, $overwrite);

// Output results
echo "<pre>";
if ($copyResults['success']) {
    echo "Successfully copied " . count($copyResults['copied_files']) . " files.\n";
    echo "Copied files:\n" . implode("\n", $copyResults['copied_files']) . "\n";
} else {
    echo "Errors occurred during copying:\n";
    if (!empty($copyResults['failed_files'])) {
        echo "Failed or skipped files:\n" . implode("\n", $copyResults['failed_files']) . "\n";
    }
    echo "Error details: " . $copyResults['error'] . "\n";
}
echo "</pre>";
?>

Download copy files and folder function code

Download copy function

Features copy files

  1. Recursive Copying:

    • Supports copying subdirectories and their contents recursively.
  2. Error Handling:

    • Detects and reports issues such as:
      • Source folder not existing or not being a directory.
      • Failure to create the destination folder.
      • Read or write errors on files.
      • Invalid destination directory.
  3. Customizable Behavior:

    • Allows enabling/disabling recursive copying via a boolean parameter.
  4. Overwrite Support:

    • Allows users to enable or disable overwriting of files in the destination directory through the $overwrite parameter.
  5. Detailed Logging:

    • Tracks:
      • Successfully copied files.
      • Files that failed to copy.
      • Overall operation success or failure.
  6. Path Normalization:

    • Ensures source and destination paths are formatted consistently by removing trailing slashes.
  7. Destination Directory Creation:

    • Automatically creates the destination directory if it does not exist, using permissions of 0755.
  8. Cross-Platform Compatibility:

    • Uses DIRECTORY_SEPARATOR for compatibility with Windows and Unix-based systems.
  9. Performance Optimization:

    • Skips unnecessary checks like copying . and .. directories.
    • Uses efficient merging of results from subdirectories.
  10. Usability:

    • Returns a structured result array, making it easy to programmatically inspect the operation results (e.g., success status, error details, and lists of files).
  11. Human-Readable Error Messages:

    • Provides clear and specific error messages for debugging and logging purposes.
  12. Suppression of Non-Fatal Errors:

    • Suppresses warnings during file copy operations with @copy() to prevent unnecessary interruption of execution.

How to Move All Files in a Folder Using PHP

The following code shows how to move all files from one folder to another:

PHP
<?php
/**
 * Moves folder contents from source to destination with an overwrite option.
 *
 * @param string $source Source directory path
 * @param string $destination Destination directory path
 * @param bool $recursive Whether to move subdirectories recursively
 * @param bool $overwrite Whether to overwrite existing files in the destination
 * @return array Operation results with success and error details
 */
function moveFolderContents(string $source, string $destination, bool $recursive = true, bool $overwrite = true): array {
    // Normalize paths to remove trailing slashes
    $source = rtrim($source, '/\\');
    $destination = rtrim($destination, '/\\');

    // Initialize results tracking
    $results = [
        'success' => true,
        'error' => null,
        'moved_files' => [],
        'failed_files' => []
    ];

    // Validate source directory
    if (!is_dir($source)) {
        $results['success'] = false;
        $results['error'] = "Source folder does not exist or is not a directory: $source";
        return $results;
    }

    // Create destination folder if it doesn't exist
    if (!file_exists($destination) && !mkdir($destination, 0755, true)) {
        $results['success'] = false;
        $results['error'] = "Cannot create destination folder: $destination";
        return $results;
    }

    // Ensure destination is a valid directory
    if (!is_dir($destination)) {
        $results['success'] = false;
        $results['error'] = "Destination is not a valid directory: $destination";
        return $results;
    }

    // Read contents of the source directory
    $items = scandir($source);
    if ($items === false) {
        $results['success'] = false;
        $results['error'] = "Failed to read source folder: $source";
        return $results;
    }

    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }

        $sourceItem = $source . DIRECTORY_SEPARATOR . $item;
        $destinationItem = $destination . DIRECTORY_SEPARATOR . $item;

        // Handle files
        if (is_file($sourceItem)) {
            if (!$overwrite && file_exists($destinationItem)) {
                // Skip overwriting the existing file
                $results['failed_files'][] = $destinationItem; // Track skipped files
                continue;
            }

            // Move file and track the result
            if (@rename($sourceItem, $destinationItem)) {
                $results['moved_files'][] = $destinationItem;
            } else {
                $results['failed_files'][] = $sourceItem;
                $results['success'] = false;
            }
        }

        // Handle directories recursively
        elseif ($recursive && is_dir($sourceItem)) {
            $subResults = moveFolderContents($sourceItem, $destinationItem, true, $overwrite);

            // Merge results from subdirectories
            $results['moved_files'] = array_merge($results['moved_files'], $subResults['moved_files']);
            $results['failed_files'] = array_merge($results['failed_files'], $subResults['failed_files']);
            if (!$subResults['success']) {
                $results['success'] = false;
            }
        }
    }

    // Remove the source folder after moving its contents
    if ($results['success'] && is_dir($source)) {
        @rmdir($source);
    }

    return $results;
}
?>

Usage Move Files Function

PHP
<?php
// Example usage
$sourceFolder = '/path/to/source/folder';
$destinationFolder = '/path/to/destination/folder';
$overwrite = false; // Set to true to enable overwriting files

$moveResults = moveFolderContents($sourceFolder, $destinationFolder, true, $overwrite);

// Output results
echo "<pre>";
if ($moveResults['success']) {
    echo "Successfully moved " . count($moveResults['moved_files']) . " files.\n";
    echo "Moved files:\n" . implode("\n", $moveResults['moved_files']) . "\n";
} else {
    echo "Errors occurred during moving:\n";
    if (!empty($moveResults['failed_files'])) {
        echo "Failed or skipped files:\n" . implode("\n", $moveResults['failed_files']) . "\n";
    }
    echo "Error details: " . $moveResults['error'] . "\n";
}
echo "</pre>";

Download folder and files move function code

Download move function

Features Move Files

  1. File and Folder Handling
    • Copy and move entire directory contents
    • Copy and move single files
    • Recursive directory traversal (with optional toggle)
    • Handles nested folder structures
    • Allows users to enable or disable overwriting
  2. Error Management
    • Detailed error reporting
    • Track successfully processed and failed files
    • Comprehensive path validation
    • Informative error messages
    • Boolean success indicator
  3. Path and Directory Management
    • Automatic destination folder creation
    • Path normalization (remove trailing slashes)
    • Cross-platform compatibility using DIRECTORY_SEPARATOR
    • Handle existing and non-existing directories
    • Validate source and destination paths
  4. Flexibility and Customization
    • Configurable recursive option
    • Separate parameters for source and destination
    • Handles various input scenarios (files, folders)
    • Minimal configuration required
  5. Performance Considerations
    • Efficient file system operations
    • Minimal overhead in processing
    • Use of native PHP functions (rename(), copy())
    • Lightweight implementation
  6. Result Tracking
    • Returned associative array with operation details
    • List of successfully moved/copied files
    • List of failed files
    • Overall operation success status
    • Optional error message
  7. Safety Features
    • Skip system directories (. and ..)
    • Prevent overwriting without confirmation
    • Robust error handling
    • Cleanup of empty source directories (move function)
  8. Logging and Reporting
    • Detailed result array for custom logging
    • Easy-to-use output method
    • Counts of processed files
    • Ability to integrate with custom logging systems
  9. Permissions and Access
    • Set default directory creation mode (0755)
    • Implicit handling of file and directory permissions
    • Silent failure with error tracking for permission issues
  10. Extensibility
    • Modular function design
    • Easy to extend or modify
    • Can be integrated into larger file management systems
    • Adaptable to specific project requirements