Change path format syntax
This commit is contained in:
parent
a4746cbf60
commit
002404d82c
|
@ -93,8 +93,8 @@ pattern.
|
||||||
|
|
||||||
Default folder structure:
|
Default folder structure:
|
||||||
```
|
```
|
||||||
dirs_path={%Y}/{%m-%b}-{city}-{folder}
|
dirs_path=<%Y>/<%m-%b>-<city>-<folder>
|
||||||
name={%Y%m%d-%H%M%S}-%u{original_name}.%l{ext}|{%Y%m%d-%H%M%S}-%u{basename}.%l{ext}
|
name=<%Y%m%d-%H%M%S>-<%u<original_name>|%u<basename>>.%l<ext>
|
||||||
```
|
```
|
||||||
|
|
||||||
Example folder structure:
|
Example folder structure:
|
||||||
|
@ -115,7 +115,7 @@ Example folder structure:
|
||||||
│ └── 20150927_014138-_dsc8705.nef
|
│ └── 20150927_014138-_dsc8705.nef
|
||||||
```
|
```
|
||||||
|
|
||||||
The folder structure use standard unix path separator (`/`). Fallback folder part can be optionally specified using a pipe (`|`) separator.
|
The folder structure use standard unix path separator (`/`). Fallback folder part can be optionally specified using a pipe separator and brackets (`<.*|.*>`).
|
||||||
|
|
||||||
Valid keywords are:
|
Valid keywords are:
|
||||||
|
|
||||||
|
|
|
@ -14,5 +14,5 @@ timeout=1
|
||||||
day_begins=4
|
day_begins=4
|
||||||
|
|
||||||
# Path format
|
# Path format
|
||||||
dirs_path={%Y}/{%m-%b}-{city}-{folder}
|
dirs_path=<%Y>/<%m-%b>-<city>-<folder>
|
||||||
name={%Y%m%d-%H%M%S}-(%u{original_name}|%u{name}).%l{ext}
|
name=<%Y%m%d-%H%M%S>-<%u<original_name>|%u<name>>.%l<ext>
|
||||||
|
|
|
@ -38,22 +38,22 @@ class FPath:
|
||||||
def get_items(self):
|
def get_items(self):
|
||||||
"""Return features items of Fpath class"""
|
"""Return features items of Fpath class"""
|
||||||
return {
|
return {
|
||||||
'album': '{album}',
|
'album': '<album>',
|
||||||
'stem': '{stem}',
|
'stem': '<stem>',
|
||||||
'camera_make': '{camera_make}',
|
'camera_make': '<camera_make>',
|
||||||
'camera_model': '{camera_model}',
|
'camera_model': '<camera_model>',
|
||||||
'city': '{city}',
|
'city': '<city>',
|
||||||
'custom': r'{".*"}',
|
'custom': r'<".*">',
|
||||||
'country': '{country}',
|
'country': '<country>',
|
||||||
'date': r'{(%[a-zA-Z][^a-zA-Z]*){1,8}}', # search for date format string
|
'date': r'<(%[a-zA-Z][^a-zA-Z]*){1,8}>', # search for date format string
|
||||||
'ext': '{ext}',
|
'ext': '<ext>',
|
||||||
'folder': '{folder}',
|
'folder': '<folder>',
|
||||||
'folders': r'{folders(\[[0-9:]{0,3}\])?}',
|
'folders': r'<folders(\[[0-9:]{0,3}\])?>',
|
||||||
'location': '{location}',
|
'location': '<location>',
|
||||||
'name': '{name}',
|
'name': '<name>',
|
||||||
'original_name': '{original_name}',
|
'original_name': '<original_name>',
|
||||||
'state': '{state}',
|
'state': '<state>',
|
||||||
'title': '{title}',
|
'title': '<title>',
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_early_morning_photos_date(self, date, mask):
|
def get_early_morning_photos_date(self, date, mask):
|
||||||
|
@ -140,6 +140,9 @@ class FPath:
|
||||||
part = stem
|
part = stem
|
||||||
for regex in utils.get_date_regex().values():
|
for regex in utils.get_date_regex().values():
|
||||||
part = re.sub(regex, '', part)
|
part = re.sub(regex, '', part)
|
||||||
|
# Delete separator
|
||||||
|
if re.search('^[-_ .]', part):
|
||||||
|
part = part[1:]
|
||||||
elif item == 'date':
|
elif item == 'date':
|
||||||
date = metadata['date_media']
|
date = metadata['date_media']
|
||||||
# early morning photos can be grouped with previous day
|
# early morning photos can be grouped with previous day
|
||||||
|
@ -194,7 +197,7 @@ class FPath:
|
||||||
for item, regex in self.items.items():
|
for item, regex in self.items.items():
|
||||||
matched = re.search(regex, this_part)
|
matched = re.search(regex, this_part)
|
||||||
if matched:
|
if matched:
|
||||||
self.log.debug(f'item: {item}, mask: {matched.group()[1:-1]}')
|
self.log.debug(f'item: {item}, mask: <matched.group()[1:-1]>')
|
||||||
part = self.get_part(item, matched.group()[1:-1], metadata)
|
part = self.get_part(item, matched.group()[1:-1], metadata)
|
||||||
self.log.debug(f'part: {part}')
|
self.log.debug(f'part: {part}')
|
||||||
|
|
||||||
|
@ -213,16 +216,16 @@ class FPath:
|
||||||
this_part = self._substitute(regex, part, this_part)
|
this_part = self._substitute(regex, part, this_part)
|
||||||
|
|
||||||
# remove alternate parts inside bracket separated by |
|
# remove alternate parts inside bracket separated by |
|
||||||
regex = r'[-_ .]?\(\|\)'
|
regex = r'[-_ .]?\<\|\>'
|
||||||
if re.search(regex, this_part):
|
if re.search(regex, this_part):
|
||||||
# Delete substitute part and separator if empty
|
# Delete substitute part and separator if empty
|
||||||
this_part = re.sub(regex, '', this_part)
|
this_part = re.sub(regex, '', this_part)
|
||||||
elif re.search(r'\(.*\)', this_part):
|
elif re.search(r'\<.*\>', this_part):
|
||||||
regex = r'\(\|'
|
regex = r'\<\|'
|
||||||
this_part = re.sub(regex, '', this_part)
|
this_part = re.sub(regex, '', this_part)
|
||||||
regex = r'\|.*\)'
|
regex = r'\|.*\>'
|
||||||
this_part = re.sub(regex, '', this_part)
|
this_part = re.sub(regex, '', this_part)
|
||||||
regex = r'\)'
|
regex = r'\>'
|
||||||
this_part = re.sub(regex, '', this_part)
|
this_part = re.sub(regex, '', this_part)
|
||||||
|
|
||||||
# Delete separator char at the begining of the string if any:
|
# Delete separator char at the begining of the string if any:
|
||||||
|
@ -238,7 +241,7 @@ class FPath:
|
||||||
|
|
||||||
def get_path(self, metadata: dict) -> list:
|
def get_path(self, metadata: dict) -> list:
|
||||||
"""
|
"""
|
||||||
path_format: {%Y-%d-%m}/%u{city}/{album}
|
path_format: <%Y-%d-%m>/%u<city>/<album>
|
||||||
Returns file path.
|
Returns file path.
|
||||||
"""
|
"""
|
||||||
path_format = self.path_format
|
path_format = self.path_format
|
||||||
|
@ -252,9 +255,9 @@ class FPath:
|
||||||
|
|
||||||
if part != '':
|
if part != '':
|
||||||
# Check if all masks are substituted
|
# Check if all masks are substituted
|
||||||
if True in [c in part for c in '{}']:
|
if True in [c in part for c in '<>']:
|
||||||
self.log.error(
|
self.log.error(
|
||||||
f"Format path part invalid: {this_part}"
|
f"Format path part invalid: {part}"
|
||||||
)
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@ def get_config_dir(name):
|
||||||
|
|
||||||
APPLICATION_DIRECTORY = get_config_dir('ordigi')
|
APPLICATION_DIRECTORY = get_config_dir('ordigi')
|
||||||
|
|
||||||
DEFAULT_PATH = '{%Y-%m-%b}/{album}|{city}'
|
DEFAULT_PATH = '<%Y-%m-%b>/<album>|<city>'
|
||||||
DEFAULT_NAME = '{%Y-%m-%d_%H-%M-%S}-{name}-{title}.%l{ext}'
|
DEFAULT_NAME = '<%Y-%m-%d_%H-%M-%S>-<name>-<title>.%l<ext>'
|
||||||
DEFAULT_PATH_FORMAT = DEFAULT_PATH + '/' + DEFAULT_NAME
|
DEFAULT_PATH_FORMAT = DEFAULT_PATH + '/' + DEFAULT_NAME
|
||||||
DEFAULT_GEOCODER = 'Nominatim'
|
DEFAULT_GEOCODER = 'Nominatim'
|
||||||
|
|
||||||
|
|
|
@ -60,8 +60,8 @@ def conf_path():
|
||||||
conf = RawConfigParser()
|
conf = RawConfigParser()
|
||||||
conf['Path'] = {
|
conf['Path'] = {
|
||||||
'day_begins': '4',
|
'day_begins': '4',
|
||||||
'dirs_path':'%u{%Y-%m}/{city}|{city}-{%Y}/{folders[:1]}/{folder}',
|
'dirs_path':'%u<%Y-%m>/<city>|<city>-<%Y>/<folders[:1]>/<folder>',
|
||||||
'name':'{%Y-%m-%b-%H-%M-%S}-{basename}.%l{ext}'
|
'name':'<%Y-%m-%b-%H-%M-%S>-<basename>.%l<ext>'
|
||||||
}
|
}
|
||||||
conf['Geolocation'] = {
|
conf['Geolocation'] = {
|
||||||
'geocoder': 'Nominatium'
|
'geocoder': 'Nominatium'
|
||||||
|
|
|
@ -33,24 +33,24 @@ class TestFPath:
|
||||||
# Item to search for:
|
# Item to search for:
|
||||||
items = fpath.get_items()
|
items = fpath.get_items()
|
||||||
masks = [
|
masks = [
|
||||||
'{album}',
|
'<album>',
|
||||||
'{basename}',
|
'<basename>',
|
||||||
'{camera_make}',
|
'<camera_make>',
|
||||||
'{camera_model}',
|
'<camera_model>',
|
||||||
'{city}',
|
'<city>',
|
||||||
'{"custom"}',
|
'<"custom">',
|
||||||
'{country}',
|
'<country>',
|
||||||
'{ext}',
|
'<ext>',
|
||||||
'{folder}',
|
'<folder>',
|
||||||
'{folders[1:3]}',
|
'<folders[1:3]>',
|
||||||
'{location}',
|
'<location>',
|
||||||
'{name}',
|
'<name>',
|
||||||
'{original_name}',
|
'<original_name>',
|
||||||
'{state}',
|
'<state>',
|
||||||
'{title}',
|
'<title>',
|
||||||
'{%Y-%m-%d}',
|
'<%Y-%m-%d>',
|
||||||
'{%Y-%m-%d_%H-%M-%S}',
|
'<%Y-%m-%d_%H-%M-%S>',
|
||||||
'{%Y-%m-%b}'
|
'<%Y-%m-%b>'
|
||||||
]
|
]
|
||||||
|
|
||||||
for file_path in self.file_paths:
|
for file_path in self.file_paths:
|
||||||
|
@ -165,7 +165,7 @@ class TestCollection:
|
||||||
|
|
||||||
collection = Collection(tmp_path, cli_options=cli_options)
|
collection = Collection(tmp_path, cli_options=cli_options)
|
||||||
# Try to change path format and sort files again
|
# Try to change path format and sort files again
|
||||||
path_format = 'test_exif/{city}/{%Y}-{name}.%l{ext}'
|
path_format = 'test_exif/<city>/<%Y>-<name>.%l<ext>'
|
||||||
summary = collection.sort_files([tmp_path], path_format, loc)
|
summary = collection.sort_files([tmp_path], path_format, loc)
|
||||||
|
|
||||||
self.assert_sort(summary, 27)
|
self.assert_sort(summary, 27)
|
||||||
|
|
|
@ -32,8 +32,8 @@ class TestConfig:
|
||||||
Read files from config and return variables
|
Read files from config and return variables
|
||||||
"""
|
"""
|
||||||
# test valid config file
|
# test valid config file
|
||||||
assert conf['Path']['dirs_path'] == '%u{%Y-%m}/{city}|{city}-{%Y}/{folders[:1]}/{folder}'
|
assert conf['Path']['dirs_path'] == '%u<%Y-%m>/<city>|<city>-<%Y>/<folders[:1]>/<folder>'
|
||||||
assert conf['Path']['name'] == '{%Y-%m-%b-%H-%M-%S}-{basename}.%l{ext}'
|
assert conf['Path']['name'] == '<%Y-%m-%b-%H-%M-%S>-<basename>.%l<ext>'
|
||||||
assert conf['Path']['day_begins'] == '4'
|
assert conf['Path']['day_begins'] == '4'
|
||||||
assert conf['Geolocation']['geocoder'] == 'Nominatium'
|
assert conf['Geolocation']['geocoder'] == 'Nominatium'
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ class TestConfig:
|
||||||
# """
|
# """
|
||||||
# config = Config(conf=conf)
|
# config = Config(conf=conf)
|
||||||
# path = config.get_path_definition()
|
# path = config.get_path_definition()
|
||||||
# assert path == '%u{%Y-%m}/{city}|{city}-{%Y}/{folders[:1]}/{folder}/{%Y-%m-%b-%H-%M-%S}-{basename}.%l{ext}'
|
# assert path == '%u<%Y-%m>/<city>|<city>-<%Y>/<folders[:1]>/<folder>/<%Y-%m-%b-%H-%M-%S>-<basename>.%l<ext>'
|
||||||
|
|
||||||
def test_get_config_options(self, conf):
|
def test_get_config_options(self, conf):
|
||||||
config = Config(conf=conf)
|
config = Config(conf=conf)
|
||||||
|
|
Loading…
Reference in New Issue