0

How do I detect the file extension of a media file missing its file extension? I accidentally removed it.

Self-Answer. The question has been asked already here and here, but the questions have been closed.

1 Answers1

0

The following Python script does the job. It will replace / append the proper filetype, if it can detect it.

  • Install Python
  • run pip install filetype in a console (more info)
  • Move the script and the media files to be checked to a separate directory
  • Double-click the script
  • follow the instructions

Tested on Windows 7. Improve the answer if you find errors. Public domain.

Other possible solutions.

The script, name it for example fix_fileextensions.py:

if __name__ == '__main__':
# make the commandline window stay open on error
from contextlib import contextmanager
from traceback import format_exc
stay_open = False
@contextmanager
def stay_open_on_error():
    global stay_open
    try:
        yield
    except SystemExit:
        stay_open = True
    except:
        print(format_exc())
        stay_open = True
    if stay_open:
        input('Press key to close')

with stay_open_on_error():

    # import some modules from the Python standard lib
    import sys, os
    from time import sleep
    from pathlib import Path

    # import the filetype package or inform user what to do
    try:
        from filetype import guess
    except ModuleNotFoundError:
        print(
            'This script uses the "filetype" package '
            'to guess the file type. '
            'Please open a console and type:\n\n'
            '    pip install filetype\n\n'
            'More info here: https://pypi.org/project/filetype/\n\n'
            'Nothing was changed.\n'
        )
        sys.exit(1)

    # define scriptpath and workdir
    scriptpath = Path(__file__).resolve()
    scriptargs = sys.argv
    if len(scriptargs) > 1:
        workdir = Path(scriptargs[1]).resolve()
        if not workdir.exists():
            raise Exception(f'Directory {workdir} does not exist')
        elif workdir.is_file():
            raise Exception('{workdir} is not a directory')
    else:
        workdir = scriptpath.parent
    scriptpath = str(scriptpath)

    # define movetodir
    c = 2
    movetodir = workdir / 'renamed'
    while movetodir.exists():
        movetodir = workdir / f'renamed ({c})'
        c += 1
    movetodir.mkdir()

    # define filesbytype
    filesbytype = {}
    for entry in os.scandir(workdir):
        filepath = entry.path
        if entry.is_dir() or filepath == scriptpath:
            continue
        else:
            info = guess(filepath)
            if info is not None:
                info = info.extension, info.mime
            if info not in filesbytype:
                filesbytype[info] = []
            filesbytype[info].append(entry.name)

    if filesbytype:

        # tool for printing unprintable filenames
        def safeprint(filename):
            try:
                print(filename)
            except UnicodeEncodeError:
                print(filename.encode('ascii', 'replace').decode())

        # tool to print a prettyprinted list of filenames
        def print_filenames(filenames):
            sep = 0
            for name in filenames:
                sep = max(sep, len(name))
            sep = (sep + 2) * '-'
            print(sep)
            for filename in filenames:
                safeprint('* ' + filename)
            print(sep)

        # print these filenames and optionally rename them
        for info, filenames in sorted(filesbytype.items()):
            if info is not None:
                print_filenames(filenames)
                filetype, mime = info
                print(
                    "\nThese files seemingly have the file type "
                    f"'.{filetype}' and the MIME type '{mime}'."
                )
                ok = input(
                    'Do you want me to append/change their extension '
                    f'to ".{filetype}"? (y/n)\n> '
                )
                if ok.lower() == 'y':
                    for filename in filenames:
                        now = workdir / filename
                        then = (movetodir / filename).with_suffix(
                            f'.{filetype}'
                        )
                        now.rename(then)
                    print(
                        f'Ok, {len(filenames)} files were renamed '
                        f'and moved to {movetodir}'
                    )
                else:
                    print('Ok, will not rename these files')
                print()

        # Maybe show the files for which the type could not be detected
        if None in filesbytype:
            print_filenames(filesbytype[None])
            print(
                '\nSorry, could not detect the file type '
                'for these files.\n'
            )

    # When the workdir is empty, print message and do nothing
    else:
        print(f'Found no files to rename in {workdir}')

    # remove the output directory when no files have been renamed
    try:
        movetodir.rmdir()
    except OSError:
        pass

    print('DONE')
    sleep(2)