Exclude folders from processing, add Page number to list view

The include folders argument changed from -x to -i
-x is used for excluding folder or files form processing

In the list view the page number and max pages is also printed out
(cosmetic)
This commit is contained in:
2018-03-07 10:24:00 +09:00
parent 869a2a647e
commit 677b2a05fb
2 changed files with 55 additions and 20 deletions

View File

@@ -21,8 +21,9 @@ See more information for [Python XMP Tool kit](http://python-xmp-toolkit.readthe
## Command line arguments
reverse_geolocate.py [-h] -x
reverse_geolocate.py [-h] -i
[XMP SOURCE FOLDER [XMP SOURCE FOLDER ...]]
[-x [EXCLUDE XMP SOURCE FOLDER [EXCLUDE XMP SOURCE FOLDER ...]]]
[-l LIGHTROOM FOLDER] [-s]
[-f <overwrite, location, city, state, country, countrycode>]
[-g GOOGLE API KEY] [-o] [-e EMIL ADDRESS] [-w]
@@ -32,7 +33,8 @@ reverse_geolocate.py [-h] -x
Argument | Argument Value | Description
--- | --- | ---
-x, --xmp | XMP sidecar source folder or XMP sidecar file itself | Must given argument. It sets the path where the script will search for XMP sidecar files. It will traverse into subdirectories. A single XMP sidecar file can also be given. If the same file folder combination is found only one is processed.
-i, --include-source | XMP sidecar source folder or XMP sidecar file itself | Must given argument. It sets the path where the script will search for XMP sidecar files. It will traverse into subdirectories. A single XMP sidecar file can also be given. If the same file folder combination is found only one is processed.
-x, --exclude-source | Folder or File | If given those files and folders will be excluded from work
-l, --lightroom | Lightroom DB base folder | The folder where the .lrcat file is located. Optional, if this is set, LR values are read before any Google maps connection is done. Fills the Latitude and Longitude and the location names. Lightroom data never overwrites data already set in the XMP sidecar file. It is recommended to have Lightroom write the XMP sidecar file before this script is run
-s, --strict | | Do strict check for Lightroom files and include the path into the check
-f, --field | Keyword: overwrite, location, city, state, country, countrycode | In the default no data is overwritten if it is already set. With the 'overwrite' flag all data is set new from the Google Maps location data. Other arguments are each of the location fields and if set only this field will be set. This can be combined with the 'overwrite' flag to overwrite already set data
@@ -53,13 +55,19 @@ If the Lightroom lookup is used without the --strict argument and several files
#### Example
```
reverse_geolocate.py -x Photos/2017/01 -x Photos/2017/02 -l LightRoom/MyCatalogue -f overwrite -g <API KEY>
reverse_geolocate.py -i Photos/2017/01 -i Photos/2017/02 -l LightRoom/MyCatalogue -f overwrite -g <API KEY>
```
Will find all XMP sidecar files in both folders *Photos/2017/01* and *Photos/2017/02* and all folder below it. Uses the Lightroom database at *LightRoom/MyCatalogue*. The script will overwrite all data, even if it is already set
```
reverse_geolocate.py -x Photos/2017/01/Event-01/some_photo.xmp -f location
reverse_geolocate.py -i Photos/2017/01 -i Photos/2017/02 -x Photos/2017/02/Folder\ A -x Photos/2017/01/Folder\ B/some_file.xmp -l LightRoom/MyCatalogue
```
Will exlucde "Photos/2017/02/Folder A" from processing. For -x also a file (including the .xmp extension) can be given.
```
reverse_geolocate.py -i Photos/2017/01/Event-01/some_photo.xmp -f location
```
Only works on *some_photo.xmp* file and will only set the *location* field if it is not yet set.

View File

@@ -13,7 +13,8 @@ import argparse, sqlite3, requests, configparser, textwrap
import glob, os, sys, re
# Note XMPFiles does not work with sidecar files, need to read via XMPMeta
from libxmp import XMPMeta, XMPError, consts
from shutil import copyfile
from shutil import copyfile, get_terminal_size
from math import ceil
##############################################################
### FUNCTIONS
@@ -33,8 +34,8 @@ class writable_dir_folder(argparse.Action):
# init new output array
out = []
# if we have a previous list in the namespace extend current list
if type(namespace.xmp_sources) is list:
out.extend(namespace.xmp_sources)
if type(getattr(namespace, self.dest)) is list:
out.extend(getattr(namespace, self.dest))
# add the new dir to it
out.append(prospective_dir)
# and write that list back to the self.dest in the namespace
@@ -350,7 +351,11 @@ def shortenPath(path, length = 30, file_only = False, path_only = False):
# RETURN: line counter +1
# DESC : prints header line and header seperator line
def printHeader(header, lines = 0, header_line = 0):
global page_no
if lines == header_line:
# add one to the pages shown and reset the lines to start new page
page_no += 1
lines = 0
# print header
print("{}".format(header))
lines += 1
@@ -376,7 +381,7 @@ parser = argparse.ArgumentParser(
# xmp folder (or folders), or file (or files)
# note that the target directory or file needs to be writeable
parser.add_argument('-x', '--xmp',
parser.add_argument('-i', '--include-source',
required = True,
nargs = '*',
action = writable_dir_folder,
@@ -384,6 +389,14 @@ parser.add_argument('-x', '--xmp',
metavar = 'XMP SOURCE FOLDER',
help = 'The source folder or folders with the XMP files that need reverse geo encoding to be set. Single XMP files can be given here'
)
# exclude folders
parser.add_argument('-x', '--exclude-source',
nargs = '*',
action = writable_dir_folder,
dest = 'exclude_sources',
metavar = 'EXCLUDE XMP SOURCE FOLDER',
help = 'Folders and files that will be excluded.'
)
# LR database (base folder)
# get .lrcat file in this folder
@@ -480,8 +493,9 @@ if not args.verbose:
args.verbose = 0
if args.debug:
print("### ARGUMENT VARS: X: {xmp}, L: {lr}, F: {fc}, M: {osm}, G: {gp}, E: {em}, N: {nbk}, W: {wrc}, V: {v}, D: {d}, T: {t}".format(
xmp = args.xmp_sources,
print("### ARGUMENT VARS: I: {incl}, X: {excl}, L: {lr}, F: {fc}, M: {osm}, G: {gp}, E: {em}, N: {nbk}, W: {wrc}, V: {v}, D: {d}, T: {t}".format(
incl = args.xmp_sources,
excl = args.exclude_sources,
lr = args.lightroom_folder,
fc = args.field_controls,
osm = args.use_openstreetmap,
@@ -662,24 +676,30 @@ xmp = XMPMeta()
for xmp_file_source in args.xmp_sources:
# if folder, open and loop
# NOTE: we do check for folders in there, if there are we recourse traverse them
if os.path.isdir(xmp_file_source):
# also check that folder is not in exclude list
if os.path.isdir(xmp_file_source) and xmp_file_source.rstrip('/') not in [x.rstrip('/') for x in args.exclude_sources]:
# open folder and look for any .xmp files and push them into holding array
# if there are folders, dive into them
# or glob glob all .xmp files + directory
for root, dirs, files in os.walk(xmp_file_source):
for file in sorted(files):
# but has no .BK. inside
if file.endswith(".xmp") and ".BK." not in file:
# 1) but has no .BK. inside
# 2) file is not in exclude list
# 3) full folder is not in exclude list
if file.endswith(".xmp") and ".BK." not in file \
and "{}/{}".format(root, file) not in args.exclude_sources \
and root.rstrip('/') not in [x.rstrip('/') for x in args.exclude_sources]:
if "{}/{}".format(root, file) not in work_files:
work_files.append("{}/{}".format(root, file))
count['all'] += 1
else:
if xmp_file_source not in work_files:
# not already added to list and not in the exclude list either
if xmp_file_source not in work_files and xmp_file_source not in args.exclude_sources:
work_files.append(xmp_file_source)
count['all'] += 1
if args.debug:
print("### Work Files {}".format(work_files))
# if we have read only we print list format style
if args.read_only:
# various string lengths
@@ -692,10 +712,14 @@ if args.read_only:
'state': 18,
'city': 20,
'location': 25,
'path': 30,
'path': 40,
}
# after how many lines do we reprint the header
header_repeat = 40;
header_repeat = 50;
# how many pages will we have
page_all = ceil(len(work_files) / header_repeat)
# current page number
page_no = 1
# the formatted line for the output
format_line = " {{filename:<{}}} | {{latitude:>{}}} | {{longitude:>{}}} | {{code:<{}}} | {{country:<{}}} | {{state:<{}}} | {{city:<{}}} | {{location:<{}}} | {{path:<{}}}".format(
format_length['filename'],
@@ -715,7 +739,7 @@ if args.read_only:
header_line = '''{}
{}
{}'''.format(
'', # can later be set to something else, eg page numbers
'> Page {page_no:,}/{page_all:,}', # can later be set to something else, eg page numbers
format_line.format( # the header title line
filename = 'File',
latitude = 'Latitude',
@@ -740,7 +764,10 @@ if args.read_only:
)
)
# print header
printHeader(header_line)
printHeader(header_line.format(page_no = page_no, page_all = page_all))
# print no files found if we have no files
if not work_files:
print("{:<60}".format('[!!!] No files found'))
# now we just loop through each file and work on them
for xmp_file in work_files:
if not args.read_only:
@@ -789,7 +816,7 @@ for xmp_file in work_files:
if args.read_only:
# for read only we print out the data formatted
# headline check, do we need to print that
count['read'] = printHeader(header_line, count['read'], header_repeat)
count['read'] = printHeader(header_line.format(page_no = page_no, page_all = page_all), count['read'], header_repeat)
# the data content
print(format_line.format(
filename = shortenPath(xmp_file, format_length['filename'], file_only = True), # shorten from the left