Ho circa 12000 immagini di diversi tipi di file, ma ognuna di esse è stata rinominata * .jpg.
Ora voglio restituire loro le loro estensioni appropriate, come posso farlo
Ho circa 12000 immagini di diversi tipi di file, ma ognuna di esse è stata rinominata * .jpg.
Ora voglio restituire loro le loro estensioni appropriate, come posso farlo
Risposte:
Puoi farlo relativamente facilmente in bash:
for f in *jpg; do
type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+')
mv "$f" "${f%%.*}.${type,,}"
done
Questa è la stessa idea della risposta di @ AB ma invece di usare globs di shell find
. La ${f%%.*}
è il nome del file, senza la sua estensione. Il -0
del file
comando permette stampare una \0
dopo il nome del file che poi utilizziamo per grep
il tipo di file. Questo dovrebbe funzionare con nomi di file arbitrari, inclusi quelli che contengono spazi, newline o altro. Il ${type,,}
è un trucco per ottenere le estensioni minuscole. Si convertirà PNG
in png
.
Non hai detto nella tua domanda, ma se hai bisogno di questo per essere ricorsivo e scendere in sottodirectory, puoi invece usare questo:
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
consentirà opzione globstar di bash che permette **
partita sottodirectory:
globstar
Se impostato, il modello ** utilizzato in un contesto di espansione del nome percorso corrisponderà a tutti i file e a zero o più directory e sottodirectory. Se il modello è seguito da un /, corrispondono solo le directory e le sottodirectory.
**
di ricorrere in sottodirectory.
file
se non sempre specifica l'estensione, a quanto pare: sta trasformando un file bash foo.bourne-again
qui, ad esempio!
Lo script seguente può essere utilizzato per rinominare (ricorsivamente) un'estensione impostata in modo errato .jpg
, con quella corretta. Nel caso in cui trovi un file illeggibile, lo riporterà nell'output dello script.
Lo script utilizza il imghdr
modulo, di riconoscere i seguenti tipi: rgb
, gif
, pbm
, pgm
, ppm
, tiff
, rast
, xbm
, jpeg
, bmp
, png
. Maggiori informazioni sul imghdr
modulo qui . L'elenco può essere esteso con più tipi, come indicato nel collegamento.
Così com'è, rinomina in modo specifico i file con l'estensione .jpg
, come indicato nella domanda. Con una modifica minore, può essere opportuno rinominare qualsiasi estensione, o un set specifico di estensioni, in quella corretta (o senza estensione, come qui ).
#!/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
Eseguilo con il comando:
python3 /path/to/rename.py <directory>
Nota: il mio approccio sembra essere troppo complesso. Preferirei la risposta di Terdon al posto tuo.
È possibile utilizzare il comando file
per determinare il tipo di file:
% 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 queste informazioni, i file possono essere rinominati:
Esegui un test prima di applicare il comando alle tue immagini
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)
}'
Esempio
% 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 "..."
e fai tutto quello che c'è dentro o usa while read -d '' name type
per dividere il nome del file e l' file
output e quindi analizzare $type
per ottenere il tipo di file. Non ne vale davvero la pena, vedi la mia risposta su come farlo molto più facilmente in puro (ish) bash.