正确的文件扩展名


15

我有大约12000张不同文件类型的图像,但是每个图像都被重命名为* .jpg。

现在我想给他们适当的扩展名,我该怎么做


2
递归还是在“平面”目录中?
Jacob Vlijm 2015年


1
@steeldriver非常接近,但是那些文件没有扩展名,这里的扩展名错误
Jacob Vlijm 2015年

1
@JacobVlijm,这就是为什么我没有将此问题标记为重复的原因:但是,答案中提出的方法在这里很有价值,恕我直言
steeldriver 2015年

@steeldriver我完全同意。
Jacob Vlijm 2015年

Answers:


22

您可以在bash中相对轻松地做到这一点:

for f in *jpg; do 
    type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+') 
    mv "$f" "${f%%.*}.${type,,}"  
done

这与@AB的答案相同,但使用的是shell glob而不是find。该${f%%.*}是没有它的扩展名。在-0该的file命令使得它打印\0的文件名,我们再使用后grep的文件类型。这应该适用于任意文件名,包括包含空格,换行符或其他任何文件名的文件名。这${type,,}是获取小写扩展名的技巧。它将转换PNGpng

您没有在问题中说,但是如果您需要递归并将其归入子目录,则可以改用以下方法:

shopt -s globstar
for f in **/*jpg; do 
    type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+') 
    mv "$f" "${f%%.*}.${type,,}"  
done

shopt -s globstar将启用bash的globstar选项,该选项可以**匹配子目录:

全球星

如果设置,则在路径名扩展上下文中使用的模式**将匹配所有文件以及零个或多个目录和子目录。如果模式后跟/,则仅目录和子目录匹配。


@AB参见更新。它允许**递归到子目录中。
terdon

每行末尾的那些分号是多余的,不是吗?
帕迪·兰道

@PaddyLandau是的,我正在将其作为一个衬板进行测试,并在此处添加了换行符以保持清晰度。我忘了删除它们。请注意,它们没有错,只是您所说的多余。
terdon 2015年

很好,尽管file似乎并不总是指定扩展名:例如,它将bash文件变成了foo.bourne-again这里!
Campa

1
@Campa不,当然不是。它还会将伪造的扩展名添加到二进制文件,普通文本文件,perl和python脚本中,并且列表继续存在。问题是专门询问图像,而这些图像的名称通常与它们通常的扩展名相同。请记住,Linux上的扩展是可选的,只有很少的例外,它们实际上不做任何事情。它们可以帮助用户整理数据,而OS则不在乎它们。
terdon 2015年

11

以下脚本可用于(递归)将错误设置的扩展名重命名为正确的扩展名.jpg。如果发现不可读的文件,它将在脚本的输出中报告该文件。

该脚本中使用的imghdr模块,识别以下几种类型:rgbgifpbmpgmppmtiffrastxbmjpegbmppng。更多关于imghdr模块的信息。如链接中所述,可以使用更多类型扩展该列表。

就这样,它专门用扩展名重命名文件.jpg,如问题中所述。进行较小的更改,就可以将任何扩展名或一组特定的扩展名重命名为正确的扩展名(或没有扩展名,如此)。

剧本:

#!/usr/bin/env python3
import os
import imghdr
import shutil
import sys

directory = sys.argv[1]

for root, dirs, files in os.walk(directory):
    for name in files:
        file = root+"/"+name
        # find files with the (incorrect) extension to rename
        if name.endswith(".jpg"):
            # find the correct extension
            ftype = imghdr.what(file)
            # rename the file
            if ftype != None:
                shutil.move(file, file.replace("jpg",ftype))
            # in case it can't be determined, mention it in the output
            else:
                print("could not determine: "+file)

如何使用

  1. 将脚本复制到一个空文件中,另存为 rename.py
  2. 通过以下命令运行它:

    python3 /path/to/rename.py <directory>
    

+1简单易读,这与基于bash的解决方案不同。
Davide 2015年

3

注意:我的方法似乎太复杂了。我希望泰顿回答您的问题。


您可以使用命令file来确定文件类型:

% file 20050101_14-24-37_330.jpg 
20050101_14-24-37_330.jpg: JPEG image data, EXIF standard 2.2, baseline, precision 8, 1200x1600, frames 3

% file test.jpg
test.jpg: PNG image data, 1192 x 774, 8-bit/color RGBA, non-interlaced

使用此信息,可以重命名文件:

在将命令应用于图像之前,请先进行测试

find . -type f -iname "*.jpg" -print0 | xargs -0 -I{} file -F"<separator>" {} | 
 awk -F " image data" '{print $1}' | 
  awk -F"<separator> " '{
   system("mv \""$1"\" $(dirname \""$1"\")/$(basename -s .jpg \"" $1 "\")."$2)
   }'

% find . -type f -name "*.jpg"
./test.jpg
./sub/20050101_14-24-37_330.jpg

% find . -type f -iname "*.jpg" -print0 | xargs -0 -I{} file -F"<separator>" {} | awk -F " image data" '{print $1}' | awk -F"<separator> " '{system ("mv \""$1"\" $(dirname \""$1"\")/$(basename -s .jpg \"" $1 "\")."$2)}'

% find . -type f -iname "*"    
./test.PNG
./sub/20050101_14-24-37_330.JPEG

请注意,这在任何文件名都包含换行符的极少数情况下都会中断。
terdon 2015年

@terdon是的,我一直在想。不幸的是,我不知道该怎么办。你能帮我吗?
AB

我不知道如何使用awk正确执行此操作。这不是工作的正确工具。使用find -exec bash -c "..."并在那里进行所有操作,或使用while read -d '' name type拆分文件名和file输出,然后解析$type以获取文件类型。真的不值得,请参阅我的回答,了解如何在纯bash中更轻松地执行此操作。
terdon 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.