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 -0de la filecommande permet d' imprimer un \0après le nom de fichier que nous utilisons ensuite greple 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 PNGen 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 globstaractivera 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.
                    filequ'il ne spécifie pas toujours l'extension qu'il semble: il transforme un fichier bash foo.bourne-againici par exemple!
                    Le script ci-dessous peut être utilisé pour (récursivement) renommer une extension incorrectement définie,, .jpgpar la bonne. S'il trouve un fichier illisible, il le signalera dans la sortie du script.
Le script utilise le imghdrmodule, pour reconnaître les types suivants: rgb, gif, pbm, pgm, ppm, tiff, rast, xbm, jpeg, bmp, png. Plus d'informations sur le imghdrmodule 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.pyExé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 filepour 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 typepour diviser le nom de fichier et la filesortie, puis analyser $typepour 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.