PHPackages                             diegobvasco/php-rsync - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [DevOps &amp; Deployment](/categories/devops)
4. /
5. diegobvasco/php-rsync

ActiveLibrary[DevOps &amp; Deployment](/categories/devops)

diegobvasco/php-rsync
=====================

A skeleton repository for my packages

v1.2.0(yesterday)03↑2900%MITPHP ^8.5.0

Since Jul 19Compare

[ Source](https://github.com/diegobvasco/php-rsync)[ Packagist](https://packagist.org/packages/diegobvasco/php-rsync)[ RSS](/packages/diegobvasco-php-rsync/feed)WikiDiscussions Synced today

READMEChangelog (4)Dependencies (6)Versions (4)Used By (0)

 [![PHP Rsync](https://raw.githubusercontent.com/diegobvasco/php-rsync/main/docs/php-rsync.webp)](https://raw.githubusercontent.com/diegobvasco/php-rsync/main/docs/php-rsync.webp)

 [![GitHub Workflow Status (master)](https://github.com/diegobvasco/php-rsync/actions/workflows/tests.yml/badge.svg)](https://github.com/diegobvasco/php-rsync/actions) [![Total Downloads](https://camo.githubusercontent.com/6e4a7b0a6d17051aad0491b7da7a80146951f3477553ff665871aa0aa130aa43/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f646965676f62766173636f2f7068702d7273796e63)](https://packagist.org/packages/diegobvasco/php-rsync) [![Latest Version](https://camo.githubusercontent.com/d4f562b7d18d03e91cdaf703746a1fc5bfd86c2f50fce3b69c2c7af9d7638d92/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f646965676f62766173636f2f7068702d7273796e63)](https://packagist.org/packages/diegobvasco/php-rsync) [![License](https://camo.githubusercontent.com/1258b28de9e3ab2d751130492d2e9cd1a289a2da1889a7a3e5d365cfe48c8ce1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f646965676f62766173636f2f7068702d7273796e63)](https://packagist.org/packages/diegobvasco/php-rsync)

---

A pure-PHP directory synchronization tool inspired by the `rsync` command. Sync directories by copying new and modified files, removing deleted files, and skipping exclusions — all with a clean fluent API.

> **Requires [PHP 8.5+](https://php.net/releases/)**

Installation
------------

[](#installation)

```
composer require diegobvasco/php-rsync
```

Usage
-----

[](#usage)

### Basic Sync

[](#basic-sync)

```
use DiegoVasconcelos\Rsync\Rsync;

$result = (new Rsync())
    ->copy('/path/to/source', '/path/to/destination')
    ->run();

echo $result->summary();
// Copied: 5 files (12.5 KB)
// Deleted: 2 files (1.2 KB)
// Skipped: 3 files
```

### With Exclusions

[](#with-exclusions)

```
$result = (new Rsync())
    ->copy('/path/to/source', '/path/to/destination')
    ->skip(['*.log', 'vendor/*', '.git', 'node_modules/'])
    ->run();

foreach ($result->copied as $file) {
    echo $file->relativePath . ' - ' . $file->formattedSize() . "\n";
}
```

### With Delete Mode

[](#with-delete-mode)

```
$result = (new Rsync())
    ->copy('/path/to/source', '/path/to/destination')
    ->delete()
    ->run();
```

### With Real-Time Output

[](#with-real-time-output)

```
use DiegoVasconcelos\Rsync\Rsync;
use DiegoVasconcelos\Rsync\TerminalOutput;

// Print each file action to the terminal as it happens
$result = (new Rsync(new TerminalOutput()))
    ->copy('/path/to/source', '/path/to/destination')
    ->delete()
    ->run();

// Output:
// COPY new-file.txt (2.5 KB)
// DELETE old-file.txt
// SKIP unchanged.txt
```

### Dry Run

[](#dry-run)

```
$result = (new Rsync())
    ->copy('/path/to/source', '/path/to/destination')
    ->delete()
    ->dryRun()
    ->run();

// No files are actually copied or deleted
echo $result->summary();
```

### Accessing Results

[](#accessing-results)

```
$result->copiedCount();    // Number of files copied
$result->deletedCount();   // Number of files deleted
$result->skippedCount();   // Number of files skipped
$result->totalBytesCopied(); // Total bytes copied
$result->copiedPaths();    // Array of copied file paths
$result->deletedPaths();   // Array of deleted file paths
$result->skippedPaths();   // Array of skipped file paths
$result->summary();        // Human-readable summary string
```

Skip Pattern Syntax
-------------------

[](#skip-pattern-syntax)

PatternMeaning`*.log`All `.log` files`vendor/*`Everything inside `vendor/``**/*.log`Any `.log` file in any subdirectory`logs/`The `logs/` directory and all its contents`??.txt`Two-character `.txt` filenames`[abc].txt`Files named `a.txt`, `b.txt`, or `c.txt``[^ab].log`Any single-character `.log` filename except `a` or `b`How It Works
------------

[](#how-it-works)

1. Scans the source directory for all files
2. Filters out files matching exclusion patterns
3. Compares each file's **modification time** and **size** against the destination
4. Copies only new or changed files
5. Deletes destination files that no longer exist in the source (when `delete()` is enabled)
6. Removes empty directories from the destination
7. Returns a `Result` object with full sync details

API
---

[](#api)

### `Rsync`

[](#rsync)

```
new Rsync(?Output $output = null)
```

The optional `Output` interface receives callbacks for each file action during sync. A `TerminalOutput` implementation is included that prints to STDOUT (or a custom stream).

#### Core

[](#core)

MethodDescription`copy(string $source, string $destination): self`Set source and destination directories`skip(string|array $patterns): self`Add glob patterns to exclude from sync`delete(): self`Enable delete mode — removes destination files not in source`recursive(): self`Enable recursive mode`archive(): self`Enable archive mode (equivalent to `-rlptgoD`)`run(): Result`Execute the sync and return results`toCommand(): string`Generate equivalent rsync shell command for debugging`reset(): self`Reset all flags and options#### Metadata Preservation

[](#metadata-preservation)

MethodDescription`times(): self`Preserve modification times (`--times`)`perms(): self`Preserve permissions (`--perms`)`owner(): self`Preserve owner (`--owner`)`group(): self`Preserve group (`--group`)`acls(): self`Preserve ACLs (`--acls`)`xattrs(): self`Preserve extended attributes (`--xattrs`)`devices(): self`Preserve device files (`--devices`)`specials(): self`Preserve special files (`--specials`)`numericIds(): self`Don't map uid/gid values (`--numeric-ids`)#### Comparison

[](#comparison)

MethodDescription`checksum(): self`Use checksum instead of mod-time &amp; size (`--checksum`)`ignoreTimes(): self`Don't skip files that match size and time (`--ignore-times`)`sizeOnly(): self`Skip files that match size only (`--size-only`)`update(): self`Skip files newer on the receiver (`--update`)#### Excludes / Includes

[](#excludes--includes)

MethodDescription`exclude(string|array $patterns): self`Add patterns to exclude (`--exclude`)`excludeFrom(string $file): self`Read exclude patterns from file (`--exclude-from`)`excludeDir(string|array $patterns): self`Add directory exclusion patterns (`--exclude-dir`)`include(string|array $patterns): self`Add patterns to include (`--include`)`includeFrom(string $file): self`Read include patterns from file (`--include-from`)`pruneEmptyDirs(): self`Remove empty directories from file list (`--prune-empty-dirs`)#### Backup

[](#backup)

MethodDescription`backup(): self`Make backups of changed files (`--backup`)`backupDir(string $dir): self`Set backup directory (`--backup-dir`)`suffix(string $suffix): self`Set backup suffix (`--suffix`)#### Symlinks / Hardlinks

[](#symlinks--hardlinks)

MethodDescription`links(): self`Copy symlinks as symlinks (`--links`)`copyLinks(): self`Transform symlinks to referent files (`--copy-links`)`copyUnsafeLinks(): self`Transform unsafe symlinks to referent files in directories (`--copy-unsafe-links`)`safeLinks(): self`Ignore symlinks that go outside tree (`--safe-links`)`hardLinks(): self`Preserve hard links (`--hard-links`)#### Size Limits

[](#size-limits)

MethodDescription`maxSize(int|string $size): self`Maximum file size to transfer (`--max-size`)`minSize(int|string $size): self`Minimum file size to transfer (`--min-size`)#### Behavior

[](#behavior)

MethodDescription`dryRun(): self`Show what would be done without doing it (`--dry-run`)`force(): self`Force deletion of non-empty directories (`--force`)`removeSourceFiles(): self`Remove source files after successful transfer (`--remove-source-files`)#### Output

[](#output)

MethodDescription`verbose(): self`Verbose output (`--verbose`)`quiet(): self`Suppress output (`--quiet`)`progress(): self`Show progress (`--progress`)`stats(): self`Show statistics (`--stats`)`itemizeChanges(): self`Show itemized changes (`--itemize-changes`)`humanReadable(): self`Human-readable numbers (`--human-readable`)#### Delete Modes

[](#delete-modes)

MethodDescription`delete(): self`Delete files in destination not in source (`--delete`)`deleteBefore(): self`Delete before transfer (`--delete-before`)`deleteAfter(): self`Delete after transfer (`--delete-after`)`deleteExcluded(): self`Delete excluded files from destination (`--delete-excluded`)### `Result`

[](#result)

MethodDescription`copiedCount(): int`Number of files copied`deletedCount(): int`Number of files deleted`skippedCount(): int`Number of files skipped`totalBytesCopied(): int`Total bytes copied`totalBytesDeleted(): int`Total bytes deleted`summary(): string`Human-readable summary`copiedPaths(): array`List of copied file paths`deletedPaths(): array`List of deleted file paths`skippedPaths(): array`List of skipped file paths### `FileInfo`

[](#fileinfo)

MethodDescription`formattedSize(): string`Human-readable file size (e.g. "12.5 KB")`formattedMtime(): string`ISO 8601 formatted modification time### `Output` (interface)

[](#output-interface)

Implement this to receive real-time file action callbacks during sync.

MethodDescription`copied(FileInfo $file): void`Called when a file is copied`deleted(FileInfo $file): void`Called when a file is deleted`skipped(FileInfo $file): void`Called when a file is skipped### `TerminalOutput`

[](#terminaloutput)

Built-in implementation of `Output` that prints actions to a stream.

```
new TerminalOutput(?resource $stream = null)
```

Defaults to `STDOUT`. Pass a custom stream to redirect output:

```
$output = new TerminalOutput(fopen('php://memory', 'r+'));
```

Quality
-------

[](#quality)

This package enforces high code quality standards:

- **100% code coverage** via Pest
- **100% type coverage** via `pestphp/pest-plugin-type-coverage`
- **PHPStan at max level** for static analysis
- **Laravel Pint** for code style
- **Rector** for automated refactoring

```
composer test          # Run entire test suite
composer test:unit     # Unit tests only
composer test:lint     # Code style check
composer test:types    # Static analysis
composer lint          # Auto-fix code style
composer refactor      # Auto-refactor code
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on recent changes.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

License
-------

[](#license)

The MIT License (MIT). Please see [LICENSE](LICENSE.md) for more information.

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance100

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

3

Last Release

1d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/e2517096d7186d249374898ba51819d519921ddf32d6100d4905dbfba83c4c5c?d=identicon)[diegobvasco](/maintainers/diegobvasco)

---

Tags

phpdeploysync

###  Code Quality

TestsPest

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/diegobvasco-php-rsync/health.svg)

```
[![Health](https://phpackages.com/badges/diegobvasco-php-rsync/health.svg)](https://phpackages.com/packages/diegobvasco-php-rsync)
```

###  Alternatives

[brunodebarros/git-deploy-php

git-deploy-php is a simple php-based tool that deploys your Git repositories to FTP/SFTP servers, and keeps them updated automatically.

2941.2k](/packages/brunodebarros-git-deploy-php)[rizeway/anchour

Toolkit for deploying web applications

265.7k](/packages/rizeway-anchour)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
