Tengo alrededor de 12000 imágenes de diferentes tipos de archivos, pero cada una de ellas pasó a llamarse * .jpg.
Ahora quiero devolverles sus extensiones adecuadas, ¿cómo puedo hacerlo?
Tengo alrededor de 12000 imágenes de diferentes tipos de archivos, pero cada una de ellas pasó a llamarse * .jpg.
Ahora quiero devolverles sus extensiones adecuadas, ¿cómo puedo hacerlo?
Respuestas:
Puedes hacerlo con relativa facilidad en bash:
for f in *jpg; do
type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+')
mv "$f" "${f%%.*}.${type,,}"
done
Esta es la misma idea que la respuesta de @ AB pero usando globos de shell en lugar de find
. El ${f%%.*}
es el nombre de archivo sin su extensión. El -0
del file
comando permite imprimir un \0
después del nombre del archivo que luego utilizamos para grep
el tipo de archivo. Esto debería funcionar con nombres de archivos arbitrarios, incluidos aquellos que contienen espacios, líneas nuevas o cualquier otra cosa. El ${type,,}
es un truco para obtener extensiones en minúsculas. Se convertiría PNG
a png
.
No dijo en su pregunta, pero si necesita que esto sea recursivo y descienda a subdirectorios, puede usar esto en su lugar:
shopt -s globstar
for f in **/*jpg; do
type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+')
mv "$f" "${f%%.*}.${type,,}"
done
El shopt -s globstar
permitirá opción Globstar de fiesta que permite a **
los subdirectorios de los partidos:
Globstar
Si se establece, el patrón ** utilizado en un contexto de expansión de nombre de ruta coincidirá con todos los archivos y cero o más directorios y subdirectorios. Si el patrón es seguido por /, solo coinciden los directorios y subdirectorios.
**
recurrir a subdirectorios.
file
no siempre especifica la extensión que parece: ¡está convirtiendo un archivo bash foo.bourne-again
aquí, por ejemplo!
El siguiente script se puede usar para cambiar el nombre (recursivamente) de una extensión establecida incorrectamente .jpg
por la correcta. En caso de que encuentre un archivo ilegible, lo informará en la salida del script.
La secuencia de comandos utiliza el imghdr
módulo, para reconocer los siguientes tipos: rgb
, gif
, pbm
, pgm
, ppm
, tiff
, rast
, xbm
, jpeg
, bmp
, png
. Más sobre el imghdr
módulo aquí . La lista se puede ampliar con más tipos, como se menciona en el enlace.
Tal como está, renombra específicamente los archivos con la extensión .jpg
, como se menciona en la pregunta. Con un cambio menor, se puede cambiar el nombre de cualquier extensión, o un conjunto específico de extensiones, a la correcta (o sin extensión, como aquí ).
#!/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
Ejecútelo con el comando:
python3 /path/to/rename.py <directory>
Nota: mi enfoque parece ser demasiado complejo. Preferiría que los terdons respondan en su lugar.
Puede usar el comando file
para determinar el tipo de archivo:
% 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
Con esta información, los archivos pueden renombrarse:
Haga una prueba antes de aplicar el comando a sus imágenes
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)
}'
Ejemplo
% 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 "..."
y haga todo lo que esté allí o use while read -d '' name type
para dividir el nombre y la file
salida del archivo y luego analizar $type
para obtener el tipo de archivo. Realmente no vale la pena, vea mi respuesta sobre cómo hacerlo mucho más fácilmente en puro (ish) bash.