Ich habe ungefähr 12000 Bilder von verschiedenen Dateitypen, aber jeder von ihnen wurde in * .jpg umbenannt.
Jetzt möchte ich ihnen ihre richtigen Erweiterungen zurückgeben, wie kann ich das tun?
Ich habe ungefähr 12000 Bilder von verschiedenen Dateitypen, aber jeder von ihnen wurde in * .jpg umbenannt.
Jetzt möchte ich ihnen ihre richtigen Erweiterungen zurückgeben, wie kann ich das tun?
Antworten:
Mit bash geht das relativ einfach:
for f in *jpg; do
type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+')
mv "$f" "${f%%.*}.${type,,}"
done
Dies ist die gleiche Idee wie bei der Antwort von @ AB, aber stattdessen werden Shell-Globs verwendet find
. Das ${f%%.*}
ist der Dateiname ohne Erweiterung. Mit -0
dem file
Befehl of wird \0
nach dem Dateinamen ein Ausdruck erstellt, den wir dann für grep
den Dateityp verwenden. Dies sollte mit beliebigen Dateinamen funktionieren, einschließlich solcher, die Leerzeichen, Zeilenumbrüche oder andere Elemente enthalten. Dies ${type,,}
ist ein Trick, um Erweiterungen in Kleinbuchstaben zu erhalten. Es würde konvertieren PNG
zu png
.
Sie haben es in Ihrer Frage nicht gesagt, aber wenn Sie möchten, dass dies rekursiv ist und in Unterverzeichnisse abfällt, können Sie stattdessen Folgendes verwenden:
shopt -s globstar
for f in **/*jpg; do
type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+')
mv "$f" "${f%%.*}.${type,,}"
done
Das shopt -s globstar
wird bash globstar Option aktivieren , die lässt **
Spiel Verzeichnisse:
globstar
Wenn festgelegt, stimmt das in einem Pfadnamen-Erweiterungskontext verwendete Muster ** mit allen Dateien und null oder mehr Verzeichnissen und Unterverzeichnissen überein. Wenn dem Muster ein / folgt, stimmen nur Verzeichnisse und Unterverzeichnisse überein.
**
das Wiederauffinden von Unterverzeichnissen.
file
nicht immer die angegebene Erweiterung angegeben wird: Es wird zum Beispiel eine Bash-Datei in diese Datei umgewandelt foo.bourne-again
!
Das folgende Skript kann verwendet werden, um eine falsch festgelegte Erweiterung (rekursiv) .jpg
in die richtige Erweiterung umzubenennen . Falls eine nicht lesbare Datei gefunden wird, wird dies in der Ausgabe des Skripts gemeldet.
Das Skript das verwendet imghdr
Modul, die folgenden Arten erkennen: rgb
, gif
, pbm
, pgm
, ppm
, tiff
, rast
, xbm
, jpeg
, bmp
, png
. Mehr zum imghdr
Modul hier . Die Liste kann, wie im Link erwähnt, um weitere Typen erweitert werden.
Wie es ist, benennt es Dateien mit der Erweiterung .jpg
, wie in der Frage erwähnt , speziell um. Mit einer geringfügigen Änderung kann eine Erweiterung oder ein bestimmter Satz von Erweiterungen in die richtige Erweiterung (oder ohne Erweiterung, wie hier ) umbenannt werden.
#!/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
Führen Sie es mit folgendem Befehl aus:
python3 /path/to/rename.py <directory>
Hinweis: Mein Ansatz scheint zu komplex zu sein. Ich würde es vorziehen, wenn Terdons an Ihrer Stelle antworten.
Mit dem Befehl können Sie file
den Dateityp bestimmen:
% 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
Mit diesen Informationen können die Dateien umbenannt werden:
Bitte führen Sie einen Test durch, bevor Sie den Befehl auf Ihre Bilder anwenden
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)
}'
Beispiel
% 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 "..."
alles, was darin enthalten ist, oder verwenden Sie while read -d '' name type
, um den Dateinamen und die file
Ausgabe zu teilen und dann zu analysieren $type
, um den Dateityp zu ermitteln. Das ist es nicht wirklich wert, siehe meine Antwort, wie man es viel einfacher in reinem (ish) bash macht.