web-dev-qa-db-fra.com

Corriger les extensions de fichier

J'ai environ 12 000 images de types de fichiers différents, mais chacune d'entre elles a été renommée * .jpg.

Maintenant, je veux leur rendre leurs extensions appropriées, comment puis-je le faire

15
akabhirav

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 @A.B, mais en utilisant des globes de shell au lieu de find. Le ${f%%.*} est le nom du fichier sans son extension. Le -0 de la commande file lui permet d'imprimer un \0 après le nom du fichier que nous utilisons ensuite pour grep son type. Cela devrait fonctionner avec des noms de fichiers arbitraires, y compris ceux qui contiennent des espaces, des nouvelles lignes ou toute autre chose. Le ${type,,} est une astuce pour obtenir des extensions minuscules. Cela convertirait PNG en png.

Vous n'avez pas dit dans votre question, mais si vous avez besoin que cela soit récursif et que vous descendiez dans des sous-répertoires, vous pouvez utiliser ceci à 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

Le shopt -s globstar activera l'option globstar de bash qui permet à ** de faire correspondre les sous-répertoires:

globstar

Si défini, le modèle ** utilisé dans un contexte d'expansion de nom de chemin correspond à tous les fichiers et à aucun ou plusieurs répertoires et sous-répertoires. Si le modèle est suivi d'un /, seuls les répertoires et les sous-répertoires correspondent.

22
terdon

Le script ci-dessous peut être utilisé pour renommer (de manière récursive) une extension mal définie, .jpg, en la correcte. S'il trouve un fichier illisible, il le signalera dans la sortie du script.

Le script utilise le module imghdr pour reconnaître les types suivants: rgb, gif, pbm, pgm, ppm, tiff, rast, xbm, jpeg, bmp, png. Plus d'informations sur le module imghdrici . La liste peut être étendue avec plusieurs types, comme mentionné dans le lien.

En l’occurrence, il renomme spécifiquement les fichiers portant l’extension .jpg, comme indiqué dans la question. Avec une modification mineure, il peut être approprié de renommer n'importe quelle extension, ou un ensemble d'extensions spécifique, en une extension correcte (ou sans extension, comme ici ).

Le scénario:

#!/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)

Comment utiliser

  1. Copiez le script dans un fichier vide, enregistrez-le sous le nom rename.py
  2. Exécutez-le à l'aide de la commande:

    python3 /path/to/rename.py <directory>
    
11
Jacob Vlijm

Remarque: mon approche semble 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 cette information, 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
3
A.B.