Пример #1
0
def map(image_path):
    """
    Show map with pins for all jpg images in the given path
    :param image_path: String with path
    :return: -
    """
    labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    labelIndex = 0

    map = Map()
    images = list_jpg(image_path)
    exifs = images_get_exifs(image_path, images, report=True)

    # Sorted list by date, so the labels will be sorted
    names = list()
    for each in exifs:
        names.append((each['createdate'], each))
    for e in sorted(names, key=lambda item: item[0]):
        if not e[1]['gps'] is None and not e[1]['gps']['lon'] is None:
            map.add_point((float(e[1]['gps']['lat']), float(e[1]['gps']['lon']), e[1]['name'],
                           e[1]['title'], e[1]['description'], labels[labelIndex % len(labels)]))
            labelIndex += 1;

    if map.count() < 1:
        print('All {} images without geo locations'.format(str(len(images))))
        return

    file_path = get_fow_root() + DIR_FOW + "/map.html"
    with open(file_path, "w") as out:
        print(map, file=out)
        webbrowser.open(file_path)
Пример #2
0
def move_corresponding_raws(jpg_dir, src_dir, dest_dir, dry_run):
    """
    Moves all corresponding raws from source directory to destination directory.
    jpg_dir is the /jpg directory with corresponding jpg files.
    src_dir is the /row directory with raws to move.
    dest_dir is the target directory.
    """
    # print('jpg=' + jpg_dir)
    # print('src=' + src_dir)
    # print('dst=' + dest_dir)

    jpgs = list_jpg(jpg_dir)
    # print(str(jpgs))

    raws = list_raw(src_dir)
    # print(str(raws))
    files = [
        r for r in raws for j in jpgs
        if filename_get_name(r) == filename_get_name(j)
    ]

    if len(files) == 0:
        print('No RAWs to move.')
        return

    if dry_run:
        print('raw files to move (may already exists):')
        for each_file in files:
            print(str(each_file))
    else:
        for each_file in files:
            os.rename(src_dir + '/' + each_file, dest_dir + '/' + each_file)
Пример #3
0
def analyse(_task, _dest):
    """
    Checks export to dest from given task.
    task: dictionary with keys 'task' (foldername/taskname),
                                'name' (task name),
                                'folder' (folder name)
    dest: String with absolut path
    Returns list with dict() for every source file, for instance:
        return [dict(name='image001.jpg', exists='true',
                src_time=1474878288.2156258,
                dst_time=1474878288.2156258)] or dst_time=None
    """
    src_dir = task.get_task_path(task.get_actual()['task']) + '/' + DIR_FINAL
    files = list_jpg(src_dir)
    # for file in files:
    # print('export_analyse() file=' + str(file) + ' '
    # + time_readable(os.path.getatime(src_dir + '/' + file)))

    ret = []
    for file in files:
        exists = os.path.exists(_dest + '/' + file)
        if exists:
            dst_time = os.path.getatime(_dest + '/' + file)
        else:
            dst_time = None

        ret.append(
            dict(name=file,
                 exists=exists,
                 src_time=os.path.getatime(src_dir + '/' + file),
                 dst_time=dst_time))

    # print('export_analyse() ret=' + str(ret))

    return ret
Пример #4
0
def map(image_path):
    """
    Show map with pins for all jpg images in the given path
    :param image_path: String with path
    :return: -
    """
    labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    labelIndex = 0

    map = Map()
    images = list_jpg(image_path)
    exifs = images_get_exifs(image_path, images, report=True)

    # Sorted list by date, so the labels will be sorted
    names = list()
    for each in exifs:
        names.append((each['createdate'], each))
    for e in sorted(names, key=lambda item: item[0]):
        if not e[1]['gps'] is None and not e[1]['gps']['lon'] is None:
            map.add_point(
                (float(e[1]['gps']['lat']), float(e[1]['gps']['lon']),
                 e[1]['name'], e[1]['title'], e[1]['description'],
                 labels[labelIndex % len(labels)]))
            labelIndex += 1

    if map.count() < 1:
        print('All {} images without geo locations'.format(str(len(images))))
        return

    file_path = get_fow_root() + DIR_FOW + "/map.html"
    with open(file_path, "w") as out:
        print(map, file=out)
        webbrowser.open(file_path)
Пример #5
0
def move_corresponding_raws(jpg_dir, src_dir, dest_dir, dry_run):
    """
    Moves all corresponding raws from source directory to destination directory.
    jpg_dir is the /jpg directory with corresponding jpg files.
    src_dir is the /row directory with raws to move.
    dest_dir is the target directory.
    """
    # print('jpg=' + jpg_dir)
    # print('src=' + src_dir)
    # print('dst=' + dest_dir)

    jpgs = list_jpg(jpg_dir)
    # print(str(jpgs))

    raws = list_raw(src_dir)
    # print(str(raws))
    files = [r for r in raws for j in jpgs
             if filename_get_name(r) == filename_get_name(j)]

    if len(files) == 0:
        print('No RAWs to move.')
        return

    if dry_run:
        print('raw files to move (may already exists):')
        for each_file in files:
            print(str(each_file))
    else:
        for each_file in files:
            os.rename(src_dir + '/' + each_file, dest_dir + '/' + each_file)
Пример #6
0
def analyse(track_path, image_path, write_path):
    """
    Analyses for gps command for all image files in the given image_path. Tracks will be searched in track_path. Both
    directories should exist and should be accessible; but they can be empty. Subdirectories are not supported, neither
    for tracks, nor for images.
    Returns a list with a dict for every image file. List can be empty.
    Supported image file types are: jpg, raw and videos; it will be always search for every image type. Other files
    will be untouched (XMP, tiff).
    Supported track files are: gpx, tcx.
    Example with explanations:
    dict=(track_path=track_path, image_path=image_path, files=
        [dict=(
            image_name='img001.raf',            # name of the image file
            image_gps= dict=(lat=123, lon=234)  # actual image file location, can be None
            tracks=['2017-03-05.gpx', ...],     # list with names of the track file, can be None
            dict=(...), ...
        ]
    """
    ret = dict(track_path=track_path, image_path=image_path, files=[], existing_track_files=[])

    images = list_video(image_path)
    images.extend(list_jpg(image_path))

    # Load all gps files
    gpx_files = os.listdir(track_path)

    patterns = []
    # for each in images:
    #     ret['files'].append(dict(image_name=each))

    exifs = images_get_exifs(image_path, images, True)
    existing_track_files = []
    # print("anlyse() exifs={}".format(str(exifs)))
    for each in exifs:
        # print("analyse() {} {}".format(str(each['name']), str(each['createdate'])))
        if not each['createdate'] is None:
            (date, time) = each['createdate'].split(" ", 1)
            (y,m,d) = date.split(':')
            # print("analyse() {}-{}-{}".format(str(y), str(m), str(d)))
            # patterns.append(".*{0}.?{1}.?{2}.*\.gpx".format(y, m, d))
            pattern = re.compile(".*{0}.?{1}.?{2}.*\.(tcx|gpx)".format(y, m, d))
            # print("analyse() {0} track_files={1}".format(each['name'], str(track_files)))
            track_files = [f for f in gpx_files if not pattern.match(f) is None]

            # Find existing track files, that would be overwritten
            if write_path is not None:
                for dest in os.listdir(write_path):
                    for src in (t for t in track_files if t == dest):
                        existing_track_files.append(src)
                        # print("analyse() exists={}".format(src))

            ret['files'].append(dict(image_name=each['name'], image_gps=each['gps'], tracks=track_files))

    ret['existing_track_files'] = list(frozenset(existing_track_files))

    # print("analyse() ret={}".format(ret))
    return ret
Пример #7
0
def check_images(path, criteria):
    """
    Try to find the images to change. Checks criteria and prints a message in error case.
    :param path:
    :param criteria: String with eihter a number or a filename to select an image. Can be "all" to select all images
    in the actual task final dir. An empty string will be interpreted as '1' (first image)
    :return: A list with file names (like os.listdir) or, in error case, None
    """

    all_files = list_jpg(path)
    # print("check_images {}".format(str(all_files)))

    if criteria == "all":
        return all_files

    if len(all_files) == 0:
        print("No images found in {}".format(str(path)))
        return None

    # Convenience for most cases
    if criteria is None:
        criteria = "1"

    # Select by number
    if re.match("^\d*$", criteria):
        nr = int(criteria)
        if nr < 1 or nr > len(all_files):
            print("Image nr doesn't match a file (must between {} and {})".format(str(1), str(len(all_files))))
            return None

        return [all_files[nr - 1]]

    # Criteria can be a file name
    for file in (f for f in all_files if f == criteria):
        return [file]

    # Unexpected criteria
    print("Criteria '{}' invalid. Must be either a number, an existing file name or 'all'".format(str(criteria)))
    return None
Пример #8
0
def analyse(_task, _dest):
    """
    Checks export to dest from given task.
    task: dictionary with keys 'task' (foldername/taskname),
                                'name' (task name),
                                'folder' (folder name)
    dest: String with absolut path
    Returns list with dict() for every source file, for instance:
        return [dict(name='image001.jpg', exists='true',
                src_time=1474878288.2156258,
                dst_time=1474878288.2156258)] or dst_time=None
    """
    src_dir = task.get_task_path(task.get_actual()['task']) + '/' + DIR_FINAL
    files = list_jpg(src_dir)
    # for file in files:
    # print('export_analyse() file=' + str(file) + ' '
    # + time_readable(os.path.getatime(src_dir + '/' + file)))

    ret = []
    for file in files:
        exists = os.path.exists(_dest + '/' + file)
        if exists:
            dst_time = os.path.getatime(_dest + '/' + file)
        else:
            dst_time = None

        ret.append(dict(
            name=file,
            exists=exists,
            src_time=os.path.getatime(src_dir + '/' + file),
            dst_time=dst_time
        ))

    # print('export_analyse() ret=' + str(ret))

    return ret
Пример #9
0
def analyse(_src, _dest_root):
    """
    Checks load from external source tree to 00_Import sub directories
    jpg, raw and video.
    _src - absolut path to external root directory
    _dest - root directory for destination's sub
    Returns dict for every source file type jpg, raw and video.
    Every dict has a list with an dict for every file with fields
        file - file name
        path - absolut path of the source file
        time - timestamp of the source file
        exist - True, if file exists in destination directory
        desttime - None, if exist is None. Otherwise timestamp of dest file

    For instance:
    { 'jpg'  : [
            { 'file'    : 'img34.jpg',
              'path'    : 'loadtest/DCIM/0001'
              'time'    : 1485803027.9297857
              'exist'   : False
              'desttime': False}', ...],
      'raw'  : [...],
      'video': [...]
    }
    """
    # print('load_analyse() _src={0}'.format(_src))

    dest_jpg = '{0}/{1}'.format(_dest_root, DIR_JPG)
    dest_raw = '{0}/{1}'.format(_dest_root, DIR_RAW)
    dest_video = '{0}/{1}'.format(_dest_root, DIR_VIDEO)
    files_jpg = list_jpg(dest_jpg)
    files_raw = list_raw(dest_raw)
    files_video = list_video(dest_video)

    values = dict(jpg=[], raw=[], video=[])
    scan_tree(_src, values)
    # print('load_analyse() files_video={0}'.format(str(files_video)))

    # Add existing info
    for each_value in values['jpg']:
        # print('each_value {0}'.format(str(each_value)))
        each_value['exist'] = False
        each_value['desttime'] = None
        for each in [e for e in files_jpg if each_value['file'] == e]:
            each_value['exist'] = True
            each_value['desttime'] = os.path.getatime('{0}/{1}'.format(
                dest_jpg, each))

    for each_value in values['raw']:
        # print('each_value {0}'.format(str(each_value)))
        each_value['exist'] = False
        each_value['desttime'] = None
        for each in [e for e in files_raw if each_value['file'] == e]:
            each_value['exist'] = True
            each_value['desttime'] = os.path.getatime('{0}/{1}'.format(
                dest_raw, each))

    for each_value in values['video']:
        # print('each_value {0}'.format(str(each_value)))
        each_value['exist'] = False
        each_value['desttime'] = None
        for each in [e for e in files_video if each_value['file'] == e]:
            each_value['exist'] = True
            each_value['desttime'] = os.path.getatime('{0}/{1}'.format(
                dest_video, each))

    # print('values {0}'.format(str(values)))

    return values
Пример #10
0
def cmd_export(cmd_list):
    """
    Copy finals to external destinations.
    """
    # 0: No param allowed, 1: param optional, 2: param obligatory
    # if not checkArgs(_arg_dict,
    #    {'-t': 0, '--test': 0, '-p': 2, '--path': 2}):
    #    return
    atom_path = dict(name='path', short='p', args=MANDATORY_PARAM)
    atom_force = dict(name='force', short='f', args=NONE_PARAM)
    atom_test = dict(name='test', short='t', args=NONE_PARAM)
    atom_none = dict(name='', short='', args=MANDATORY_PARAM)

    ret = check_rules(cmd_list, [[
        dict(atom=atom_path, obligat=True),
        dict(atom=atom_force, obligat=False),
        dict(atom=atom_test, obligat=False)
    ],
                                 [
                                     dict(atom=atom_none, obligat=True),
                                     dict(atom=atom_force, obligat=False),
                                     dict(atom=atom_test, obligat=False)
                                 ]])

    if ret['message'] is not None:
        return

    # Get destination
    if 'path' in ret['options']:
        destination = ret['options']['path']
    else:
        try:
            destination = config.read_pickle()[plump.EXPORT_PREFIX + '.' +
                                               ret['options']['']]
        except:
            print(
                "Destination value not defined. Create it with config -s='export.{}' first."
                .format(ret['options']['']))
            return

    if destination is None:
        print('Destination not valid. See "help export".')
        return

    # Extract task specific subdirectory {1} or {2}, if given
    m = re.compile('(.*)(/{[12]}/?)').match(destination)

    # Direct path
    if m is None:
        if not os.path.exists(destination):
            print('Destination directory not reachable: ' + destination)
            return

    # Task specific path
    else:
        root_dir = m.group(1)
        if os.path.exists(m.group(1)):
            # Resolve subdirectory placeholder: task name
            if destination.endswith(('{1}', '{1}/')):
                destination = root_dir + '/' + task.get_actual()['name']
            # Resolve subdirectory placeholder: folder + task name
            elif destination.endswith(('{2}', '{2}/')):
                destination = root_dir + '/' + task.get_actual()['task']
        else:
            print('Destination root directory not reachable: ' + root_dir)
            return

    print('destination={}'.format(destination))
    if not task.check_actual():
        return

    src_dir = task.get_actual()['task'] + '/' + plump.DIR_FINAL
    src_path = task.get_task_path(src_dir)
    files = plump.list_jpg(src_path)

    # [dict(name='image001.jpg', exists='true')]
    analysis = export.analyse(task.get_actual(), destination)
    if 'test' in ret['options']:
        export.test(analysis, src_dir, destination)
        return

    # export --force
    if 'force' in ret['options']:
        print(
            str(len(files)) + ' images in ' + task.get_actual()['task'] + '/' +
            plump.DIR_FINAL)
        print('Destination: ' + destination)
        export.copy(analysis, src_path, destination)

    # export
    else:
        exists = False
        for item in analysis:
            if item['exists']:
                exists = True
        if exists:
            print('Files would be overwritten! ' +
                  'Use --test to list the file(s) ' +
                  'or use --force to overwrite the image(s). ')
        else:
            print(
                str(len(files)) + ' images in ' + task.get_actual()['task'] +
                '/' + plump.DIR_FINAL)
            print('Destination: ' + destination)
            export.copy(analysis, src_path, destination)
Пример #11
0
def analyse(track_path, image_path, write_path):
    """
    Analyses for gps command for all image files in the given image_path. Tracks will be searched in track_path. Both
    directories should exist and should be accessible; but they can be empty. Subdirectories are not supported, neither
    for tracks, nor for images.
    Returns a list with a dict for every image file. List can be empty.
    Supported image file types are: jpg, raw and videos; it will be always search for every image type. Other files
    will be untouched (XMP, tiff).
    Supported track files are: gpx, tcx.
    Example with explanations:
    dict=(track_path=track_path, image_path=image_path, files=
        [dict=(
            image_name='img001.raf',            # name of the image file
            image_gps= dict=(lat=123, lon=234)  # actual image file location, can be None
            tracks=['2017-03-05.gpx', ...],     # list with names of the track file, can be None
            dict=(...), ...
        ]
    """
    ret = dict(track_path=track_path,
               image_path=image_path,
               files=[],
               existing_track_files=[])

    images = list_video(image_path)
    images.extend(list_jpg(image_path))

    # Load all gps files
    gpx_files = os.listdir(track_path)

    patterns = []
    # for each in images:
    #     ret['files'].append(dict(image_name=each))

    exifs = images_get_exifs(image_path, images, True)
    existing_track_files = []
    # print("anlyse() exifs={}".format(str(exifs)))
    for each in exifs:
        # print("analyse() {} {}".format(str(each['name']), str(each['createdate'])))
        if not each['createdate'] is None:
            (date, time) = each['createdate'].split(" ", 1)
            (y, m, d) = date.split(':')
            # print("analyse() {}-{}-{}".format(str(y), str(m), str(d)))
            # patterns.append(".*{0}.?{1}.?{2}.*\.gpx".format(y, m, d))
            pattern = re.compile(".*{0}.?{1}.?{2}.*\.(tcx|gpx)".format(
                y, m, d))
            # print("analyse() {0} track_files={1}".format(each['name'], str(track_files)))
            track_files = [
                f for f in gpx_files if not pattern.match(f) is None
            ]

            # Find existing track files, that would be overwritten
            if write_path is not None:
                for dest in os.listdir(write_path):
                    for src in (t for t in track_files if t == dest):
                        existing_track_files.append(src)
                        # print("analyse() exists={}".format(src))

            ret['files'].append(
                dict(image_name=each['name'],
                     image_gps=each['gps'],
                     tracks=track_files))

    ret['existing_track_files'] = list(frozenset(existing_track_files))

    # print("analyse() ret={}".format(ret))
    return ret
Пример #12
0
def analyse(_src, _dest_root):
    """
    Checks load from external source tree to 00_Import sub directories
    jpg, raw and video.
    _src - absolut path to external root directory
    _dest - root directory for destination's sub
    Returns dict for every source file type jpg, raw and video.
    Every dict has a list with an dict for every file with fields
        file - file name
        path - absolut path of the source file
        time - timestamp of the source file
        exist - True, if file exists in destination directory
        desttime - None, if exist is None. Otherwise timestamp of dest file

    For instance:
    { 'jpg'  : [
            { 'file'    : 'img34.jpg',
              'path'    : 'loadtest/DCIM/0001'
              'time'    : 1485803027.9297857
              'exist'   : False
              'desttime': False}', ...],
      'raw'  : [...],
      'video': [...]
    }
    """
    # print('load_analyse() _src={0}'.format(_src))

    dest_jpg = '{0}/{1}'.format(_dest_root, DIR_JPG)
    dest_raw = '{0}/{1}'.format(_dest_root, DIR_RAW)
    dest_video = '{0}/{1}'.format(_dest_root, DIR_VIDEO)
    files_jpg = list_jpg(dest_jpg)
    files_raw = list_raw(dest_raw)
    files_video = list_video(dest_video)

    values = dict(jpg=[], raw=[], video=[])
    scan_tree(_src, values)
    # print('load_analyse() files_video={0}'.format(str(files_video)))

    # Add existing info
    for each_value in values['jpg']:
        # print('each_value {0}'.format(str(each_value)))
        each_value['exist'] = False
        each_value['desttime'] = None
        for each in [e for e in files_jpg if each_value['file'] == e]:
            each_value['exist'] = True
            each_value['desttime'] = os.path.getatime('{0}/{1}'.format(
                dest_jpg, each))

    for each_value in values['raw']:
        # print('each_value {0}'.format(str(each_value)))
        each_value['exist'] = False
        each_value['desttime'] = None
        for each in [e for e in files_raw if each_value['file'] == e]:
            each_value['exist'] = True
            each_value['desttime'] = os.path.getatime('{0}/{1}'.format(
                dest_raw, each))

    for each_value in values['video']:
        # print('each_value {0}'.format(str(each_value)))
        each_value['exist'] = False
        each_value['desttime'] = None
        for each in [e for e in files_video if each_value['file'] == e]:
            each_value['exist'] = True
            each_value['desttime'] = os.path.getatime('{0}/{1}'.format(
                dest_video, each))

    # print('values {0}'.format(str(values)))

    return values
Пример #13
0
def analyse(src_path, dest_path):
    """
    Analyses for renaming command for all image files in the given path.
    Returns a list with a dict for every file. List can be empty.
    Supported image file types are: jpg, raw and videos; it will be
    always search for every image type. Other files will be untouched
    (XMP, tiff).
    Example with explanations:
    dict=(src_path=src_path, dest_path=dest_path, files=
        [dict=(
            subdir='RAW'
            old_name='img001.raf',                 #file name in src_path
            new_name='20161131-123456-img001.raf', #new image name
            exists=True),                      #False, if no file name conflict
                                                   #in dest_path
            dict=(...), ...
        ]
    """
    ret = []

    subdir = DIR_JPG
    files = list_jpg(src_path + '/' + subdir)
    index = 0
    progress = progress_prepare(len(files), 'Processing', subdir)
    for each in files:
        # print(str(image_get_time(path)))
        index += 1
        sys.stdout.write(progress['back'] + progress['formatting'].format(str(index)))
        sys.stdout.flush()
        old_name = each
        time_str = image_get_time(src_path + '/' + subdir + '/' + each)
        if time_str is None:
            new_name = old_name
        else:
            new_name = time_str + '-' + old_name

        if os.path.exists(dest_path + '/' + subdir + '/' + new_name):
            exists = True
        else:
            exists = False

        ret.append(dict(subdir=subdir, old_name=old_name, new_name=new_name,
                        exists=exists))
    sys.stdout.write('\n')

    subdir = DIR_RAW
    files = list_raw(src_path + '/' + subdir)
    index = 0
    progress = progress_prepare(len(files), 'Processing', subdir)
    for each in files:
        # print(str(image_get_time(path)))
        index += 1
        sys.stdout.write(progress['back'] + progress['formatting'].format(str(index)))
        sys.stdout.flush()
        old_name = each
        time_str = image_get_time(src_path + '/' + subdir + '/' + each)
        if time_str is None:
            new_name = old_name
        else:
            new_name = time_str + '-' + old_name

        if os.path.exists(dest_path + '/' + subdir + '/' + new_name):
            exists = True
        else:
            exists = False

        ret.append(dict(subdir=subdir, old_name=old_name, new_name=new_name,
                        exists=exists))
    sys.stdout.write('\n')

    subdir = DIR_VIDEO
    files = list_video(src_path + '/' + subdir)
    index = 0
    progress = progress_prepare(len(files), 'Processing', subdir)
    for each in files:
        # print(str(image_get_time(path)))
        index += 1
        sys.stdout.write(progress['back'] + progress['formatting'].format(str(index)))
        sys.stdout.flush()
        old_name = each
        time_str = video_get_time(src_path + '/' + subdir + '/' + each)
        if time_str is None:
            new_name = old_name
        else:
            new_name = time_str + '-' + old_name

        if os.path.exists(dest_path + '/' + subdir + '/' + new_name):
            exists = True
        else:
            exists = False

        ret.append(dict(subdir=subdir, old_name=old_name, new_name=new_name,
                        exists=exists))

    sys.stdout.write('\n')

    return dict(src_path=src_path, dest_path=dest_path, files=ret)
Пример #14
0
def cmd_export(cmd_list):
    """
    Copy finals to external destinations.
    """
    # 0: No param allowed, 1: param optional, 2: param obligatory
    # if not checkArgs(_arg_dict,
    #    {'-t': 0, '--test': 0, '-p': 2, '--path': 2}):
    #    return
    atom_path = dict(name='path', short='p', args=MANDATORY_PARAM)
    atom_force = dict(name='force', short='f', args=NONE_PARAM)
    atom_test = dict(name='test', short='t', args=NONE_PARAM)
    atom_none = dict(name='', short='', args=MANDATORY_PARAM)

    ret = check_rules(cmd_list,
                      [
                          [
                              dict(atom=atom_path, obligat=True),
                              dict(atom=atom_force, obligat=False),
                              dict(atom=atom_test, obligat=False)
                          ],
                          [
                              dict(atom=atom_none, obligat=True),
                              dict(atom=atom_force, obligat=False),
                              dict(atom=atom_test, obligat=False)
                          ]
                      ])

    if ret['message'] is not None:
        return

    # Get destination
    if 'path' in ret['options']:
        destination = ret['options']['path']
    else:
        try:
            destination = config.read_pickle()[plump.EXPORT_PREFIX + '.' + ret['options']['']]
        except:
            print("Destination value not defined. Create it with config -s='export.{}' first."
                  .format(ret['options']['']))
            return

    if destination is None:
        print('Destination not valid. See "help export".')
        return

    # Extract task specific subdirectory {1} or {2}, if given
    m = re.compile('(.*)(/{[12]}/?)').match(destination)

    # Direct path
    if m is None:
        if not os.path.exists(destination):
            print('Destination directory not reachable: ' + destination)
            return

    # Task specific path
    else:
        root_dir = m.group(1)
        if os.path.exists(m.group(1)):
            # Resolve subdirectory placeholder: task name
            if destination.endswith(('{1}', '{1}/')):
                destination = root_dir + '/' + task.get_actual()['name']
            # Resolve subdirectory placeholder: folder + task name
            elif destination.endswith(('{2}', '{2}/')):
                destination = root_dir + '/' + task.get_actual()['task']
        else:
            print('Destination root directory not reachable: ' + root_dir)
            return

    print('destination={}'.format(destination))
    if not task.check_actual():
        return

    src_dir = task.get_actual()['task'] + '/' + plump.DIR_FINAL
    src_path = task.get_task_path(src_dir)
    files = plump.list_jpg(src_path)

    # [dict(name='image001.jpg', exists='true')]
    analysis = export.analyse(task.get_actual(), destination)
    if 'test' in ret['options']:
        export.test(analysis, src_dir, destination)
        return

    # export --force
    if 'force' in ret['options']:
        print(str(len(files)) + ' images in ' + task.get_actual()['task']
              + '/' + plump.DIR_FINAL)
        print('Destination: ' + destination)
        export.copy(analysis, src_path, destination)

    # export
    else:
        exists = False
        for item in analysis:
            if item['exists']:
                exists = True
        if exists:
            print('Files would be overwritten! ' +
                  'Use --test to list the file(s) ' +
                  'or use --force to overwrite the image(s). ')
        else:
            print(str(len(files)) + ' images in ' + task.get_actual()['task']
                  + '/' + plump.DIR_FINAL)
            print('Destination: ' + destination)
            export.copy(analysis, src_path, destination)