Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,21 @@ Or you can sort by year without century, then week number, then an abbreviated d

The possibilities go on and on.

## original source directory structure
The default behavior is to omit the original directory structure in the source directory and to move or copy the files to the formatted date directories under the destination directory. By using the -p/--preserve-dir option, the original source directory structure will be preserved and created under the destination directory as well as the formatted date directories.

For example, with an original directory structure of:

src/dir1/dir2/file

The default behavior will lead to:

dst/2014/08-Aug/file

With -p/--preserve-dir, we get:

dst/dir1/dir2/2014/08-Aug/file

## duplicate removal
SortPhotos will *always* check to make sure something with the same file name doesn't already exist where it's trying to write, so that you don't unintentionally overwrite a file. It this occurs it will append a number on the end of the file. So for example if photo.jpg was taken on June 1, 2010 but 2010 > June > photo.jpg already exists then the new file will be copied as photo_1.jpg and so on. SortPhotos will go one step further and if it finds a file of the same name, it will then run a file compare to see if the files are actually the same. If they are *exactly* the same, it will just skip the copy (or move) operation. This will prevent you from having duplicate files. However you have the option of turning this off (not the name comparison, that will always happen, just the weeding out of duplicates). This option would be useful, for example, if you are copying over a bunch of new photos that you are sure don't already exist in your organized collection of photos. It's a little faster to skip duplicate detection. Invoke the option ``--keep-duplicates`` in order to skip duplicate detection.

Expand Down
38 changes: 19 additions & 19 deletions src/sortphotos.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def get_creation_time(path):
# --------- main script -----------------

def sortPhotos(src_dir, dest_dir, extensions, sort_format, move_files, removeDuplicates,
ignore_exif, day_begins):
ignore_exif, day_begins, preserve_dirs):


# some error checking
Expand Down Expand Up @@ -145,17 +145,20 @@ def sortPhotos(src_dir, dest_dir, extensions, sort_format, move_files, removeDup
if case_sensitive_os:
matches += fnmatch.filter(filenames, '*.' + ext.upper())

# add file root and save the matched file in list
# save the matched file's relative dir, and its name
for match in matches:
matched_files.append(os.path.join(root, match))
rel_path = os.path.relpath(root, src_dir)
matched_files.append((rel_path, match))


# setup a progress bar
num_files = len(matched_files)
idx = 0


for src_file in matched_files:
for file_rel_path, file_name in matched_files:
# full original file name
src_file = os.path.join(src_dir, file_rel_path, file_name)

# update progress bar
numdots = int(20.0*(idx+1)/num_files)
Expand Down Expand Up @@ -194,16 +197,16 @@ def sortPhotos(src_dir, dest_dir, extensions, sort_format, move_files, removeDup
date = check_for_early_morning_photos(date, day_begins)

# create folder structure
dir_structure = date.strftime(sort_format)
dirs = dir_structure.split('/')
dest_file = dest_dir
for thedir in dirs:
dest_file = os.path.join(dest_file, thedir)
if not os.path.exists(dest_file):
os.makedirs(dest_file)
dest_file_dirs = [dest_dir]
if preserve_dirs:
dest_file_dirs.append(file_rel_path)
dest_file_dirs += date.strftime(sort_format).split('/')
dest_file = os.path.join(*dest_file_dirs)
if not os.path.exists(dest_file):
os.makedirs(dest_file)

# setup destination file
dest_file = os.path.join(dest_file, os.path.basename(src_file))
dest_file = os.path.join(dest_file, file_name)
root, ext = os.path.splitext(dest_file)

# check for collisions
Expand Down Expand Up @@ -234,11 +237,6 @@ def sortPhotos(src_dir, dest_dir, extensions, sort_format, move_files, removeDup
else:
shutil.copy2(src_file, dest_file)


print



if __name__ == '__main__':

import argparse
Expand All @@ -249,12 +247,13 @@ def sortPhotos(src_dir, dest_dir, extensions, sort_format, move_files, removeDup
parser.add_argument('src_dir', type=str, help='source directory (searched recursively)')
parser.add_argument('dest_dir', type=str, help='destination directory')
parser.add_argument('-m', '--move', action='store_true', help='move files instead of copy')
parser.add_argument('-p', '--preserve-dirs', action='store_true', help='preserve original src_dir folder structure while moving or copying to dest_dir')
parser.add_argument('-s', '--sort', type=str, default='%Y/%m-%b',
help="choose destination folder structure using datetime format \n\
https://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior. \n\
Use forward slashes / to indicate subdirectory(ies) (independent of your OS convention). \n\
The default is '%%Y/%%m-%%b', which separates by year then month \n\
with both the month number and name (e.g., 2012/12-Feb).")
with both the month number and name (e.g., 2012/02-Feb).")
parser.add_argument('--keep-duplicates', action='store_true',
help='If file is a duplicate keep it anyway (after renmaing).')
parser.add_argument('--extensions', type=str, nargs='+',
Expand All @@ -270,7 +269,8 @@ def sortPhotos(src_dir, dest_dir, extensions, sort_format, move_files, removeDup
args = parser.parse_args()

sortPhotos(args.src_dir, args.dest_dir, args.extensions, args.sort,
args.move, not args.keep_duplicates, args.ignore_exif, args.day_begins)
args.move, not args.keep_duplicates, args.ignore_exif,
args.day_begins, args.preserve_dirs)