Oihana PHP

copyFilteredFiles.php

Table of Contents

Functions

copyFilteredFiles()  : bool
Recursively copies files and directories from a source to a destination with filtering.

Functions

copyFilteredFiles()

Recursively copies files and directories from a source to a destination with filtering.

copyFilteredFiles(string $sourceDir, string $destDir[, array<string|int, string> $excludePatterns = [] ][, callable|null $filterCallback = null ][, bool $followLinks = false ]) : bool

This function iterates through a source directory and copies its contents to a destination directory, preserving the folder structure. It provides two methods for filtering which files and directories get copied:

  1. $excludePatterns: An array of glob/regex patterns. Any file or directory matching a pattern in this array will be skipped. See shouldExcludeFile().
  2. $filterCallback: An optional user-defined function. This callback receives the full path of each item and must return true for the item to be copied.

Destination directories are created as needed.

Symbolic links. By default a link is reproduced as a link, with the target it was written with: a relative link stays relative, an absolute one stays absolute, and the target is never read, so nothing is copied through a link. Pass $followLinks to read them instead — a linked directory is then walked and a linked file copied, as if the link were the thing it points at. A link pointing at nothing is skipped either way. Both the exclude patterns and the filter callback see the link's own path, not its target's.

Parameters
$sourceDir : string

The path to the source directory to copy from.

$destDir : string

The path to the destination directory.

$excludePatterns : array<string|int, string> = []

An array of patterns to exclude from the copy.

$filterCallback : callable|null = null

Optional callback for custom filtering. It receives the file path and should return true to include it.

$followLinks : bool = false

Whether to read symbolic links instead of reproducing them (Default false).

Tags
throws
DirectoryException

If a directory cannot be created in the destination path, if a file cannot be copied, if a symbolic link cannot be reproduced, or if $followLinks meets a link pointing at a directory that holds it.

security

$excludePatterns is forwarded to shouldExcludeFile() which uses fnmatch() (glob) or preg_match() (regex). Patterns must come from a trusted source — a malicious regex can cause CPU exhaustion (ReDoS) since PHP's regex engine has no execution timeout. See the security guide.

$followLinks reads whatever the links in the source point at, which may be anywhere on the disk and outside the source directory. A link pointing at a directory that holds the link itself is refused, since reading it would not end, but two links pointing at each other's branch are not detected — the same caveat as findFiles().

example

Source directory structure:

/tmp/source/
├── .git/
│   └── config
├── images/
│   └── logo.png  (size: 5KB)
├── index.php     (size: 1KB)
└── error.log
$source = '/tmp/source';
$destination = '/tmp/destination';

// Exclude .git directories and all .log files.
$exclude = ['.git', '*.log'];

// Only include files smaller than 2KB (2048 bytes).
$filter = function(string $filePath)
{
   return is_dir($filePath) || filesize($filePath) < 2048;
};

copyFilteredFiles($source, $destination, $exclude, $filter);

Resulting destination directory:

/tmp/destination/
├── images/
└── index.php

Explanation:

  • .git/ was skipped by the exclude pattern.
  • error.log was skipped by the exclude pattern.
  • images/logo.png was skipped by the filter callback (size > 2KB).
  • index.php was copied as it passed both filters.

A link, reproduced and then read:

symlink( '/var/data/uploads' , '/tmp/source/uploads' ) ;

copyFilteredFiles( '/tmp/source' , '/tmp/mirror' ) ;
// /tmp/mirror/uploads is a link to /var/data/uploads, nothing was read through it.

copyFilteredFiles( '/tmp/source' , '/tmp/backup' , followLinks: true ) ;
// /tmp/backup/uploads is a real directory holding a copy of what /var/data/uploads contains.
author

Marc Alcaraz (ekameleon)

since
1.0.0
Return values
bool —

Returns true if at least one file or directory was copied, false otherwise.

On this page

Search results