我从故障的外部硬盘复制了大量图片。所有图片都完好无损,但奇怪的是,其中很多现在缺少扩展名。这些文件是 jpg、png 和 gif 的混合体,并以以下结构命名,全部位于一个文件夹中。
1
2
3
4.jpg
5.png
etc
有些文件有扩展名,但很多文件没有扩展名,只有数字。此文件夹中大约有 4000 张图片,因此无法手动重命名。
是否有任何脚本或程序可用于通过元数据确定扩展名并根据需要将其添加到文件中?
多年来我一直使用软件中心的“pyrenamer”来重命名文件,但它似乎无法添加扩展名。
任何帮助都将不胜感激,我的编码很糟糕,我无法独自弄清楚。
答案1
下面是一个 Python 解决方案(脚本)。
该脚本使用imghdr 模块识别文件类型。它将添加以下类型的正确文件扩展名(如果缺失):
rgb, gif, pbm, pgm, ppm, tiff, rast, xbm, jpeg, bmp, png
如果文件已经有文件扩展名,则会跳过它。如果文件属于未知文件类型(例如,如果文件已损坏),则会将文件报告为“无法确定”:
could not determine: /home/jacob/Bureaublad/picturetest/blub
剧本:
#!/usr/bin/env python3
import os
import imghdr
import shutil
directory = "/path/to/pictures"
for name in os.listdir(directory):
# combining file+its directory:
file = directory+"/"+name
# only files without a dot are subject to renaming (else the file already has a file extension or is a hidden file):
if name.count(".") == 0:
# fetch the file extension from the file:
ftype = imghdr.what(file)
# if it is impossible to get the extension (if the file is damaged for example), the file(s) will be listed in the terminal window:
if ftype != None:
shutil.move(file, file+"."+ftype)
else:
print("could not determine: "+file)
将其粘贴到一个空文件中,另存为rename.py,在行中将目录设置为图片directory = "/path/to/pictures"
,然后通过命令运行:
python3 /path/to/rename.py
递归重命名
如果您的图片不在“平面”目录中,而是在分层目录中,请使用以下版本。它将检查(并在必要时修复)文件当前文件夹中的文件扩展名。
#!/usr/bin/env python3
import os
import imghdr
import shutil
directory = "/path/to/pictures"
for root, dirs, files in os.walk(directory):
for name in files:
file = root+"/"+name
if name.count(".") == 0:
ftype = imghdr.what(file)
if ftype != None:
shutil.move(file, file+"."+ftype)
else:
print("could not determine: "+file)
答案2
使用以下命令rename
:
rename 's/.*/use File::MimeInfo::Magic qw#mimetype extensions#; sprintf("%s.%s", $&, extensions(mimetype($&)))/e' * -vn
它使用 PerlFile::MimeInfo
模块来查询文件(类似于命令的操作方式file
)来确定文件是什么,然后将 MimeInfo 对该 MIME 类型的第一个扩展名附加到文件中。
在某些情况下,这可能会导致使用不太常用的扩展名(例如,大多数人将 jpg 文件命名为 jpeg 或 jpe),但您可以进行第二次尝试以轻松纠正这些问题:
rename 's/\.jpe$/.jpg/' *
但是大多数应用程序不会介意您指定 .jpe 文件,因此大多数情况下这不是必需的。
上述两个rename
命令均设置为测试模式。除非您从末尾
删除参数,否则它们不会执行任何操作。-n
答案3
简单脚本
#!/bin/bash
for file in ~/path/to/images/*; do
TYPE=$(file --mime-type -b "$file" | cut -f2 -d/);
if [[ ! $file =~ \.$TYPE ]]; then
echo mv -v "$file" "$file.$TYPE";
fi
done
TYPE=$(file --mime-type -b "$file" | cut -f2 -d/);
(查找文件类型)的解释
$file
使用file
(确定文件类型)命令查找每个文件的扩展名。
--mime-type, --mime-encoding
用于仅打印指定元素的选项。
-b, --brief
用于不将文件名添加到输出行(简短模式)的选项。
另请参阅man 文件了解更多信息。
现在我们提取文件类型并将其保存到TYPE
变量中。
那么命令是什么cut -f2 -d/
?这用于打印扩展类型,就像结果的输出png
一样。image/png
file --mime-type -b "$file"
-f2
打印第二部分,字段之间使用/
分隔符(-d
选项)。例如:打印png
在image/png
。另请参阅人切了解更多信息。
if [[...]];
(检查文件扩展名)的解释
我们使用一个简单的正则表达式跳过所有现有的扩展,在 if 条件测试=~
中使用运算符[[...]]
:
if [[ $file =~ \.$TYPE ]];
而$file
是您的图像文件名,$TYPE
是其扩展名,我们发现并将其存储到TYPE
变量中TYPE=$(file --mime-type -b "$file" | cut -f2 -d/);
。
然后我们跳过重命名所有带有其自身扩展名的文件。
!
参考:如果文件本身没有扩展名,则重命名并在其名称末尾添加扩展名。
echo mv -v "$file" "$file.$TYPE";
(重命名步骤)说明
在这一行中,实际上我们使用命令$file
在文件末尾附加文件扩展名(如果没有其自身的扩展名) 。也用于重命名文件/目录。$file
mv
mv
然后我们将其重命名$file
为$file.$TYPE
。例如,如果文件类型为格式,则文件1
将被重命名为。1.png
png
in theory actually above mv command do this: rename filename -> filename.filetype
该文件名存储在$file
变量中,文件类型存储在$TYPE
变量中。
如何使用这个脚本?
复制并粘贴脚本gedit
并以您喜欢的名称保存它,例如:batchRename
,然后打开终端并通过以下命令运行它:
bash batchRename
在运行脚本之前不要忘记验证图像路径是否正确/path/to/images/
,并在使用命令检查结果后对文件进行重命名echo
,echo
从头开始删除echo mv -v "$file" "$file.$TYPE"
并再次运行脚本并享受重命名;)