J'ai environ 12000 images de différents types de fichiers, mais chacune d'elles a été renommée * .jpg.
Maintenant, je veux leur rendre leurs extensions appropriées, comment puis-je le faire
J'ai environ 12000 images de différents types de fichiers, mais chacune d'elles a été renommée * .jpg.
Maintenant, je veux leur rendre leurs extensions appropriées, comment puis-je le faire
Réponses:
Vous pouvez le faire relativement facilement en bash:
for f in *jpg; do
type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+')
mv "$f" "${f%%.*}.${type,,}"
done
C'est la même idée que la réponse de @ AB mais en utilisant des globes shell à la place de find
. Le ${f%%.*}
est le nom du fichier sans son extension. La -0
de la file
commande permet d' imprimer un \0
après le nom de fichier que nous utilisons ensuite grep
le type de fichier. Cela devrait fonctionner avec des noms de fichiers arbitraires, y compris ceux qui contiennent des espaces, des retours à la ligne ou toute autre chose. C'est ${type,,}
une astuce pour obtenir des extensions minuscules. Il se convertirait PNG
en png
.
Vous n'avez pas dit dans votre question, mais si vous avez besoin que cela soit récursif et descende dans des sous-répertoires, vous pouvez l'utiliser à la place:
shopt -s globstar
for f in **/*jpg; do
type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+')
mv "$f" "${f%%.*}.${type,,}"
done
L' shopt -s globstar
activera l'option globstar de bash qui permet de faire **
correspondre les sous-répertoires:
globstar
S'il est défini, le modèle ** utilisé dans un contexte d'extension de chemin correspondra à tous les fichiers et à zéro ou plusieurs répertoires et sous-répertoires. Si le modèle est suivi d'un /, seuls les répertoires et sous-répertoires correspondent.
**
de rentrer dans des sous-répertoires.
file
qu'il ne spécifie pas toujours l'extension qu'il semble: il transforme un fichier bash foo.bourne-again
ici par exemple!
Le script ci-dessous peut être utilisé pour (récursivement) renommer une extension incorrectement définie,, .jpg
par la bonne. S'il trouve un fichier illisible, il le signalera dans la sortie du script.
Le script utilise le imghdr
module, pour reconnaître les types suivants: rgb
, gif
, pbm
, pgm
, ppm
, tiff
, rast
, xbm
, jpeg
, bmp
, png
. Plus d'informations sur le imghdr
module ici . La liste peut être étendue avec plus de types, comme mentionné dans le lien.
En l'état, il renomme spécifiquement les fichiers avec l'extension .jpg
, comme mentionné dans la question. Avec un changement mineur, il peut être approprié de renommer n'importe quelle extension, ou un ensemble spécifique d'extensions, en la bonne (ou sans extension, comme ici ).
#!/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
Exécutez-le par la commande:
python3 /path/to/rename.py <directory>
Remarque: Mon approche semble être trop complexe. Je préférerais que les terdons répondent à votre place.
Vous pouvez utiliser la commande file
pour déterminer le type de fichier:
% 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
Avec ces informations, les fichiers peuvent être renommés:
Veuillez faire un test avant d'appliquer la commande à vos images
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)
}'
Exemple
% 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 "..."
et tout faire là-dedans, soit utiliser while read -d '' name type
pour diviser le nom de fichier et la file
sortie, puis analyser $type
pour obtenir le type de fichier. Ça ne vaut pas vraiment le coup, voir ma réponse pour savoir comment le faire beaucoup plus facilement en pure (ish) bash.