У меня есть около 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
of 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
не всегда указывает расширение, которое кажется: оно превращает bash-файл foo.bourne-again
сюда, например!
Сценарий ниже может быть использован (рекурсивно) для переименования неправильно установленного расширения .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
чтобы получить тип файла. На самом деле не стоит, смотрите мой ответ о том, как сделать это намного проще в чистом (ish) bash.