Skip to content

Instantly share code, notes, and snippets.

@staydecent
Last active October 22, 2025 22:13
Show Gist options
  • Select an option

  • Save staydecent/271f943dc94383b51f9bd16c650b0d55 to your computer and use it in GitHub Desktop.

Select an option

Save staydecent/271f943dc94383b51f9bd16c650b0d55 to your computer and use it in GitHub Desktop.
Organize photos found in same folder as script, into year/month/day folders
#!/usr/bin/env php
<?php
date_default_timezone_set('America/Vancouver');
define('DS', DIRECTORY_SEPARATOR);
define('ROOT', getcwd() . DS);
/**
* ------------------------------------------------------------------------
* Configuration options
* ------------------------------------------------------------------------
*/
$photoExts = [
"jpg",
"jpeg",
"png",
"tiff",
"dng",
# Sony
"arw",
"sr2",
"srf",
# Canon
"crw",
"cr2",
"cr3",
# Nikon
"nef",
"nrw",
# Fujifilm
"3fr",
"raf",
# Panasonic
"rw2",
# Olympus
"orf",
# Pentax
"pef",
];
/**
* ------------------------------------------------------------------------
* Functions
* ------------------------------------------------------------------------
*/
function getPhotoDateTakenOrFileDate($filePath) {
if (!file_exists($filePath)) {
return false;
}
$foundDate = false;
$exifData = @exif_read_data($filePath);
if ($exifData !== false && isset($exifData['DateTimeOriginal'])) {
try {
$dateTimeOriginal = $exifData['DateTimeOriginal'];
$date = DateTime::createFromFormat('Y:m:d H:i:s', $dateTimeOriginal);
if ($date !== false) {
$foundDate = $date->format('Y-m-d');
}
} catch (Exception $e) {
return false;
}
}
$fileModificationTime = filemtime($filePath);
if ($fileModificationTime !== false) {
$foundDate = date("Y-m-d", $fileModificationTime);
}
if (! $foundDate) {
return false;
} else {
$dateTaken = DateTime::createFromFormat('Y-m-d', $foundDate);
if (!$dateTaken) {
throw new InvalidArgumentException("Invalid date format. Expected format is 'Y-m-d'.");
}
return $dateTaken;
}
}
function move_file($sourceFileInfo, $destDir) {
if (! is_dir($destDir)) {
mkdir($destDir, 0777, true);
}
if (! rename($sourceFileInfo->getPathname(), $destDir . DS . $sourceFileInfo->getBasename())) {
printf("Could not move photo: \"%s\"\n", $sourceFileInfo->getPathname());
} else {
echo "Moved photo! " . $destDir . DS . $sourceFileInfo->getBasename();
}
}
/**
* ------------------------------------------------------------------------
* Iterate images
* ------------------------------------------------------------------------
*/
$dir = new DirectoryIterator(ROOT);
foreach ($dir as $fileInfo) {
if ( ! $fileInfo->isDot()
&& in_array(strtolower($fileInfo->getExtension()), $photoExts)
&& substr($fileInfo->getBasename(), '0', 1) !== '.') {
echo "Found photo: " . $fileInfo->getPathname() . "\n";
$dateTaken = getPhotoDateTakenOrFileDate($fileInfo->getPathname());
if (! $dateTaken) {
echo "No date found." . "\n";
} else {
$newDir = $fileInfo->getPath()
. DS . $dateTaken->format('Y')
. DS . $dateTaken->format('m')
. DS . $dateTaken->format('d');
move_file($fileInfo, $newDir);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment