2017-11-26 12:26:47 +01:00
#!/usr/bin/env python
2015-06-04 04:28:47 +02:00
import os
import os . path
2017-11-30 22:39:17 +01:00
from time import localtime , strftime
2015-11-29 14:35:13 +01:00
import shutil
2017-11-30 22:37:56 +01:00
import jpgSorter
import numberOfFilesPerFolderLimiter
2021-11-16 23:27:09 +01:00
import exifread
from time import localtime , strftime , strptime , mktime
2017-11-30 22:37:56 +01:00
2017-11-30 22:39:17 +01:00
2015-12-06 01:53:14 +01:00
def getNumberOfFilesInFolderRecursively ( start_path = ' . ' ) :
numberOfFiles = 0
2015-11-29 14:35:13 +01:00
for dirpath , dirnames , filenames in os . walk ( start_path ) :
for f in filenames :
fp = os . path . join ( dirpath , f )
2015-12-06 01:53:14 +01:00
if ( os . path . isfile ( fp ) ) :
2017-11-25 19:24:30 +01:00
numberOfFiles + = 1
2015-12-06 01:53:14 +01:00
return numberOfFiles
2015-09-17 20:29:05 +02:00
2015-12-06 03:16:17 +01:00
2015-12-06 01:53:14 +01:00
def getNumberOfFilesInFolder ( path ) :
2017-11-25 19:24:30 +01:00
return len ( os . listdir ( path ) )
2015-09-17 20:29:05 +02:00
2015-12-06 03:16:17 +01:00
2015-12-06 01:53:14 +01:00
def log ( logString ) :
2017-11-25 19:24:30 +01:00
print ( strftime ( " % H: % M: % S " , localtime ( ) ) + " : " + logString )
2015-12-06 01:53:14 +01:00
2015-12-06 03:16:17 +01:00
def moveFile ( file , destination ) :
2017-11-25 19:24:30 +01:00
extension = os . path . splitext ( file ) [ 1 ] [ 1 : ] . upper ( )
sourcePath = os . path . join ( root , file )
2017-11-25 19:21:49 +01:00
2017-11-25 19:24:30 +01:00
destinationDirectory = os . path . join ( destination , extension )
2015-12-06 03:16:17 +01:00
2017-11-25 19:24:30 +01:00
if not os . path . exists ( destinationDirectory ) :
os . mkdir ( destinationDirectory )
2017-11-25 19:21:49 +01:00
2017-11-25 19:24:30 +01:00
fileName = str ( fileCounter ) + " . " + extension . lower ( )
destinationFile = os . path . join ( destinationDirectory , fileName )
if not os . path . exists ( destinationFile ) :
shutil . copy ( sourcePath , destinationFile )
2015-12-06 03:16:17 +01:00
2017-11-26 12:23:12 +01:00
def get_args ( ) :
import argparse
description = (
" Sort files recoverd by Photorec. \n "
" The input files are first copied to the destination, sorted by file type. \n "
" Then JPG files are sorted based on creation year (and optionally month). \n "
" Finally any directories containing more than a maximum number of files are accordingly split into separate directories. "
)
parser = argparse . ArgumentParser ( description = description , formatter_class = argparse . ArgumentDefaultsHelpFormatter )
parser . add_argument ( ' source ' , metavar = ' src ' , type = str , help = ' source directory with files recovered by Photorec ' )
parser . add_argument ( ' destination ' , metavar = ' dest ' , type = str , help = ' destination directory to write sorted files to ' )
parser . add_argument ( ' -n ' , ' --max-per-dir ' , type = int , default = 500 , required = False , help = ' maximum number of files per directory ' )
parser . add_argument ( ' -m ' , ' --split-months ' , action = ' store_true ' , required = False , help = ' split JPEG files not only by year but by month as well ' )
2017-11-30 22:20:36 +01:00
parser . add_argument ( ' -k ' , ' --keep_filename ' , action = ' store_true ' , required = False , help = ' keeps the original filenames when copying ' )
2017-11-30 22:48:57 +01:00
parser . add_argument ( ' -d ' , ' --min-event-delta ' , type = int , default = 4 , required = False , help = ' minimum delta in days between two days ' )
2021-11-16 23:47:43 +01:00
parser . add_argument ( ' -j ' , ' --date_time_filename ' , action = ' store_true ' , required = False , help = ' sets the filename to the exif date and time if possible - otherwise keep the original filename ' )
2017-11-26 12:23:12 +01:00
return parser . parse_args ( )
2015-12-06 03:16:17 +01:00
2015-12-06 01:53:14 +01:00
maxNumberOfFilesPerFolder = 500
2017-11-26 12:23:12 +01:00
splitMonths = False
2015-11-29 14:35:13 +01:00
source = None
destination = None
2017-11-30 22:20:36 +01:00
keepFilename = False
2021-11-16 23:27:09 +01:00
date_time_filename = False
2015-09-18 20:03:07 +02:00
2017-11-26 12:23:12 +01:00
args = get_args ( )
source = args . source
destination = args . destination
maxNumberOfFilesPerFolder = args . max_per_dir
splitMonths = args . split_months
2017-11-30 22:20:36 +01:00
keepFilename = args . keep_filename
2021-11-16 23:27:09 +01:00
date_time_filename = args . date_time_filename
2017-11-30 22:48:57 +01:00
minEventDeltaDays = args . min_event_delta
2017-11-26 12:23:12 +01:00
print ( " Reading from source ' %s ' , writing to destination ' %s ' (max %i files per directory, splitting by year %s ). " %
( source , destination , maxNumberOfFilesPerFolder , splitMonths and " and month " or " only " ) )
2017-11-30 22:20:36 +01:00
if keepFilename :
print ( " I will keep you filenames as they are " )
2021-11-16 23:27:09 +01:00
elif date_time_filename :
2021-11-16 23:47:43 +01:00
print ( " If possible I will rename your files like <Date>_<Time>.jpg - otherwise keep the filenames as they are " )
2017-11-30 22:20:36 +01:00
else :
print ( " I will rename your files like ' 1.jpg ' " )
2015-12-06 01:53:14 +01:00
2015-11-29 14:35:13 +01:00
while ( ( source is None ) or ( not os . path . exists ( source ) ) ) :
2017-11-25 19:24:30 +01:00
source = input ( ' Enter a valid source directory \n ' )
2015-11-29 14:35:13 +01:00
while ( ( destination is None ) or ( not os . path . exists ( destination ) ) ) :
2017-11-25 19:24:30 +01:00
destination = input ( ' Enter a valid destination directory \n ' )
2015-09-17 20:29:05 +02:00
2015-12-06 03:16:17 +01:00
fileNumber = getNumberOfFilesInFolderRecursively ( source )
2021-11-16 23:06:11 +01:00
if fileNumber > 100 :
onePercentFiles = int ( fileNumber / 100 )
else :
onePercentFiles = fileNumber
2015-12-06 03:16:17 +01:00
totalAmountToCopy = str ( fileNumber )
2015-12-06 01:53:14 +01:00
print ( " Files to copy: " + totalAmountToCopy )
2015-09-17 20:29:05 +02:00
2015-12-06 01:53:14 +01:00
fileCounter = 0
2015-06-04 04:28:47 +02:00
for root , dirs , files in os . walk ( source , topdown = False ) :
2015-12-06 03:16:17 +01:00
2017-11-25 19:24:30 +01:00
for file in files :
extension = os . path . splitext ( file ) [ 1 ] [ 1 : ] . upper ( )
sourcePath = os . path . join ( root , file )
2017-11-25 19:21:49 +01:00
2022-04-12 16:22:05 +02:00
if extension :
destinationDirectory = os . path . join ( destination , extension )
else :
destinationDirectory = os . path . join ( destination , " _NO_EXTENSION " )
2015-11-29 14:35:13 +01:00
2017-11-25 19:24:30 +01:00
if not os . path . exists ( destinationDirectory ) :
os . mkdir ( destinationDirectory )
2021-11-16 23:27:09 +01:00
2017-11-30 22:20:36 +01:00
if keepFilename :
fileName = file
2021-11-16 23:27:09 +01:00
elif date_time_filename :
index = 0
image = open ( sourcePath , ' rb ' )
exifTags = exifread . process_file ( image , details = False )
image . close ( )
creationTime = jpgSorter . getMinimumCreationTime ( exifTags )
try :
creationTime = strptime ( str ( creationTime ) , " % Y: % m: %d % H: % M: % S " )
creationTime = strftime ( " % Y % m %d _ % H % M % S " , creationTime )
fileName = str ( creationTime ) + " . " + extension . lower ( )
while os . path . exists ( os . path . join ( destinationDirectory , fileName ) ) :
index + = 1
fileName = str ( creationTime ) + " ( " + str ( index ) + " ) " + " . " + extension . lower ( )
except :
fileName = file
2017-11-30 22:20:36 +01:00
else :
2022-04-12 16:22:05 +02:00
if extension :
fileName = str ( fileCounter ) + " . " + extension . lower ( )
else :
fileName = str ( fileCounter )
2017-11-25 19:21:49 +01:00
2017-11-25 19:24:30 +01:00
destinationFile = os . path . join ( destinationDirectory , fileName )
if not os . path . exists ( destinationFile ) :
shutil . copy2 ( sourcePath , destinationFile )
2015-12-06 01:53:14 +01:00
2017-11-25 19:24:30 +01:00
fileCounter + = 1
2021-06-26 14:00:38 +02:00
if ( ( fileCounter % onePercentFiles ) == 0 ) :
2017-11-25 19:24:30 +01:00
log ( str ( fileCounter ) + " / " + totalAmountToCopy + " processed. " )
2015-12-06 01:53:14 +01:00
log ( " start special file treatment " )
2017-11-30 22:48:57 +01:00
jpgSorter . postprocessImages ( os . path . join ( destination , " JPG " ) , minEventDeltaDays , splitMonths )
2015-12-06 01:53:14 +01:00
log ( " assure max file per folder number " )
numberOfFilesPerFolderLimiter . limitFilesPerFolder ( destination , maxNumberOfFilesPerFolder )