答案1
以下 Python 脚本可完成此任务。如果可以检测到,它将替换/附加正确的文件类型。
在 Windows 7 上测试。如果发现错误,请改进答案。公共领域。
脚本,例如命名它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)