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 -0del filecomando permite imprimir un \0después del nombre del archivo que luego utilizamos para grepel 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 PNGa 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 globstarpermitirá 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.
fileno siempre especifica la extensión que parece: ¡está convirtiendo un archivo bash foo.bourne-againaquí, por ejemplo!
El siguiente script se puede usar para cambiar el nombre (recursivamente) de una extensión establecida incorrectamente .jpgpor la correcta. En caso de que encuentre un archivo ilegible, lo informará en la salida del script.
La secuencia de comandos utiliza el imghdrmódulo, para reconocer los siguientes tipos: rgb, gif, pbm, pgm, ppm, tiff, rast, xbm, jpeg, bmp, png. Más sobre el imghdrmó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.pyEjecú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 filepara 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 typepara dividir el nombre y la filesalida del archivo y luego analizar $typepara 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.