У мене є близько 12000 зображень різних типів файлів, але кожне з них було перейменовано * .jpg.
Тепер я хочу повернути їм належне розширення, як це зробити
У мене є близько 12000 зображень різних типів файлів, але кожне з них було перейменовано * .jpg.
Тепер я хочу повернути їм належне розширення, як це зробити
Відповіді:
Ви можете зробити це відносно легко в 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
Якщо встановлено, шаблон **, який використовується в контексті розширення імені шляху, буде відповідати всім файлам, нульовим або більше каталогів і підкаталогів. Якщо за шаблоном дотримується /, відповідають лише каталоги та підкаталоги.
**
повторно вписатись у підкаталоги.
file
не завжди вказується розширення. Здається, це foo.bourne-again
сюди, наприклад , перетворює bash-файл !
Сценарій нижче може використовуватися для (рекурсивного) перейменування неправильно встановленого розширення, .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)
rename.py
Виконайте команду:
python3 /path/to/rename.py <directory>
Примітка: Мій підхід здається занадто складним. Я вважаю за краще тердон відповіді на вашому місці.
За допомогою команди 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
find -exec bash -c "..."
та виконайте все, що є там, або використовуйте, while read -d '' name type
щоб розділити ім’я та file
вихід файлу, а потім проаналізувати, $type
щоб отримати тип файлу. Справді не варто, дивіться мою відповідь, як зробити це набагато легше в чистому (іш) баші.