Виправте розширення файлів


15

У мене є близько 12000 зображень різних типів файлів, але кожне з них було перейменовано * .jpg.

Тепер я хочу повернути їм належне розширення, як це зробити


2
рекурсивно, або в "плоскій" каталог?
— Яків Влійм


1
@steeldriver досить близько, але ці файли не мають розширення, тут вони мають неправильне розширення.
— Яків Влійм

1
@JacobVlijm, тому я не позначив це питання як дублікат: проте методи, запропоновані у відповідях, мають значення тут, IMHO
— steeldriver

@steeldriver я повністю згоден.
— Яків Влійм

Відповіді:


22

Ви можете зробити це відносно легко в bash:

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

Це та сама ідея, що і у відповіді @ AB, але замість цього використовується оболонка find. Ім'я ${f%%.*}файлу без його розширення. -0З fileкоманди робить його надрукувати \0після імені файлу , який ми потім використовувати для grepтипу файлу. Це повинно працювати з довільними іменами файлів, у тому числі з тими, що містять пробіли, нові рядки чи що-небудь інше. Це ${type,,}трюк, щоб отримати невеликі розширення. Це перетвориться PNGна png.

Ви не сказали у своєму запитанні, але якщо вам потрібно, щоб це було рекурсивно і переходило до підкаталогів, ви можете використовувати це замість цього:

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Буде включити опцію globstar Баша, який дозволяє **матч підкаталогів:

globstar

Якщо встановлено, шаблон **, який використовується в контексті розширення імені шляху, буде відповідати всім файлам, нульовим або більше каталогів і підкаталогів. Якщо за шаблоном дотримується /, відповідають лише каталоги та підкаталоги.


@AB див. Оновлення. Це дозволяє **повторно вписатись у підкаталоги.
— terdon

Ці крапки з комою в кінці кожного рядка є зайвими, чи не так?
— Падді Ландау

@PaddyLandau так, я тестував його як один вкладиш і додав сюди нові рядки для наочності. Я забув їх видалити. Зауважте, що вони не помиляються, просто зайві, як ви кажете.
— тердон

Чудово, хоча fileне завжди вказується розширення. Здається, це foo.bourne-againсюди, наприклад , перетворює bash-файл !
— Кампа

1
@Campa ні, звичайно ні. Це також додасть фіктивних розширень до двійкових файлів, звичайних текстових файлів, сценаріїв perl та python, і список продовжується. Питання стосувалося конкретних зображень, і вони, як правило, мають те саме ім'я, що і їх звичайні розширення. Пам'ятайте, що розширення на Linux необов’язкові, за дуже невеликими винятками, вони насправді нічого не роблять. Вони допомагають користувачеві впорядковувати свої дані, ОС їх не хвилює.
— тердон

11

Сценарій нижче може використовуватися для (рекурсивного) перейменування неправильно встановленого розширення, .jpgу правильне. Якщо він знайде файл, який не можна прочитати, він повідомить про це у висновку сценарію.

Сценарій використовувати imghdrмодуль, щоб розпізнавати такі типи: rgb, gif, pbm, pgm, ppm, tiff, rast, xbm, jpeg, bmp, png. Детальніше про 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 для простого і легкого для читання, на відміну від рішень на базі.
— Девіде

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 Так, я думав. На жаль, я не маю уявлення, що я можу зробити. Ви можете допомогти?
— AB

Я поняття не маю, як це правильно зробити за допомогою awk. Це не правильний інструмент для роботи. Або використовуйте find -exec bash -c "..."та виконайте все, що є там, або використовуйте, while read -d '' name typeщоб розділити ім’я та fileвихід файлу, а потім проаналізувати, $typeщоб отримати тип файлу. Справді не варто, дивіться мою відповідь, як зробити це набагато легше в чистому (іш) баші.
— тердон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.