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


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.