def run(args):
    #Reset wipes the destination clean so we can start over.
    if args.reset:
        reset(args)

    #Set up validates the destination and source directories.
    #It also loads the previous state or creates one as necessary.
    state = setup(args)

    #We break out of this loop in batch mode and on KeyboardInterrupt
    while True:

        #The file scan uses the arguments and the state to filter down to
        #only new (since the last sync time) files.
        for path in scan(args, state):
            try:
                #Read the file and expose useful aspects for renaming/filtering
                replay = sc2reader.load_replay(path, load_level=2)
            except __HOLE__:
                raise
            except:
                #Failure to parse
                file_name = os.path.basename(path)
                directory = make_directory(args, ('parse_error',))
                new_path = os.path.join(directory, file_name)
                source_path = path[len(args.source):]
                args.log.write("Error parsing replay: {0}".format(source_path))
                if not args.dryrun:
                    args.action.run(path, new_path)

                #Skip to the next replay
                continue

            aspects = generate_aspects(args, replay)

            #Use the filter args to select files based on replay attributes
            if filter_out_replay(args, replay):
                continue

            #Apply the aspects to the rename formatting.
            #'/' is a special character for creation of subdirectories.
            #TODO: Handle duplicate replay names, its possible..
            path_parts = args.rename.format(**aspects).split('/')
            filename = path_parts.pop()+'.SC2Replay'

            #Construct the directory and file paths; create needed directories
            directory = make_directory(args, path_parts)
            new_path = os.path.join(directory, filename)

            #Find the source relative to the source directory for reporting
            dest_path = new_path[len(args.dest):]
            source_path = path[len(args.source):]

            #Log the action and run it if we are live
            msg = "{0}:\n\tSource: {1}\n\tDest: {2}\n"
            args.log.write(msg.format(args.action.type, source_path, dest_path))
            if not args.dryrun:
                args.action.run(path, new_path)

        #After every batch completes, save the state and flush the log
        #TODO: modify the state to include a list of remaining files
        args.log.flush()
        save_state(state, args)

        #We only run once in batch mode!
        if args.mode == 'BATCH':
            break

        #Since new replays come in fairly infrequently, reduce system load
        #by sleeping for an acceptable response time before the next scan.
        time.sleep(args.period)

    args.log.write('Batch Completed')
dataset/ETHPy150Open GraylinKim/sc2reader/examples/sc2autosave.py/run