I created this script to keep my external hard drive synchronized with my different PCs. I needed it to work both by pulling from PC to external, and reverse because sometimes I change things on the external hard drive with one PC and need to sync back to the other. If a file / folder exists in the same location on both it doesn't check which is newer / last modified it only makes sure the same files and folders are present in both locations.

So the usage is something like this (.bat):

@ECHO off
echo Synchonizing D:\Documents with P:\Documents
php C:\syncDirs.php -- D:\Documents P:\Documents
PAUSE

And the script itself:

<?php

set_time_limit(0);

// Get directories specified by command line arguments
$dir1 = isset($argv[2]) ? $argv[2] : NULL;
$dir2 = isset($argv[3]) ? $argv[3] : NULL;

// If 2 directories weren't specified, exit the script
if( is_null($dir1) || is_null($dir2) ) die('Invalid or missing arguments.');

synchronizeDirs($dir1,$dir2);
synchronizeDirs($dir2,$dir1);
synchronizeDirs();

function synchronizeDirs($source = '',$dest = '') {
	static $newDirs = 0;
	static $newFiles = 0;

// If called without arguments, echo number of directories and files this function created
if( empty($source) && empty($dest) ) {
	echo "\nTotal Directories created: $newDirs\nTotal Files Copies: $newFiles\n\n";
	return;
}

// Trim trailing slash(es)
$source = rtrim($source,'/\\');
$dest = rtrim($dest,'/\\');

// Verify the arguments passed
if( !is_dir($source) || !is_readable($source) ) {
	trigger_error('Source is not a valid directory or is not readable',E_USER_ERROR);
}
if( !is_dir($dest) ) {
	if( !mkdir($dest,777) ) {
		trigger_error('Unable to create destination directory',E_USER_ERROR);
	}
} elseif( !is_writeable($dest) ) {
	if( !chmod($dest,777) ) {
		trigger_error('Unable to write to destination directory',E_USER_ERROR);
	}
}

// Fix file / folder names with brackets for glob usage
$tSource = preg_replace('/(\*|\?|\[)/', '[$1]', $source).DIRECTORY_SEPARATOR.'*';
$tDest = preg_replace('/(\*|\?|\[)/', '[$1]', $dest).DIRECTORY_SEPARATOR.'*';

$globSource = glob($tSource);
if( $globSource === FALSE ) {
	trigger_error('Unable to get contents of '.$source,E_USER_ERROR);
}

$globDest = glob($tDest);
if( $globDest === FALSE ) {
	trigger_error('Unable to get contents of '.$dest,E_USER_ERROR);
}

foreach( $globSource as $file ) {
	// Skip all .ini files
	if( pathinfo($file,PATHINFO_EXTENSION) == 'ini' ) continue;

	// Target location to go with current file/folder from source
	$targ = $dest.DIRECTORY_SEPARATOR.basename($file);

	if( is_file($file) ) {
		if( !file_exists($targ) ) {
			echo "\tCopying to $targ...\n";
			copy($file,$dest.DIRECTORY_SEPARATOR.basename($file));
			$newFiles++;
		}
	} elseif( is_dir($file) ) {
		if( !is_dir($targ) ) {
			echo "\tCreating $targ...\n";
			mkdir($targ,777);
			$newDirs++;
		}
		synchronizeDirs($file,$targ);
	}
}
}

Thoughts? Any ways to improve it? Thanks for looking =D

    I believe rsync is also available for Windows, and is the standard tool for keeping files synced between systems.

      bradgrafelman;11003433 wrote:

      Any reason you're not just using a tool that comes with Windows, e.g. Robocopy?

      EDIT: If you didn't want any of Robocopy's fancy options, you could even step down a bit to Xcopy.

      Mainly because I just like to see if I can do it. Most of the scripts I make are just to see if I can get them to work. Unfortunately I don't really do anything for pay because no one wants to pay me lol, but I like the challenge of creating something even if it already exists.

        I use SyncToy on my computer and rsync on my Ubuntu server.

        But this is a really cool script!

          Write a Reply...