Saya memiliki sekitar 12000 gambar dari jenis file yang berbeda tetapi masing-masing dari mereka diganti namanya * .jpg.
Sekarang saya ingin memberi mereka ekstensi yang tepat kembali, bagaimana saya bisa melakukannya
Saya memiliki sekitar 12000 gambar dari jenis file yang berbeda tetapi masing-masing dari mereka diganti namanya * .jpg.
Sekarang saya ingin memberi mereka ekstensi yang tepat kembali, bagaimana saya bisa melakukannya
Jawaban:
Anda dapat melakukannya dengan relatif mudah di bash:
for f in *jpg; do
type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+')
mv "$f" "${f%%.*}.${type,,}"
done
Ini adalah ide yang sama dengan jawaban @ AB tetapi menggunakan shell shell sebagai gantinya find
. Ini ${f%%.*}
adalah nama file tanpa ekstensi. The -0
dari file
perintah membuatnya mencetak \0
setelah nama file yang kemudian kita gunakan untuk grep
jenis file. Ini harus bekerja dengan nama file yang sewenang-wenang, termasuk yang berisi spasi, baris baru atau apa pun. Ini ${type,,}
adalah trik untuk mendapatkan ekstensi huruf kecil. Itu akan dikonversi PNG
menjadi png
.
Anda tidak mengatakan dalam pertanyaan Anda, tetapi jika Anda ingin ini bersifat rekursif dan turun ke subdirektori, Anda bisa menggunakan ini sebagai gantinya:
shopt -s globstar
for f in **/*jpg; do
type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+')
mv "$f" "${f%%.*}.${type,,}"
done
Opsi ini shopt -s globstar
akan mengaktifkan bash's globstar yang memungkinkan **
mencocokkan subdirektori:
globstar
Jika diatur, pola ** yang digunakan dalam konteks ekspansi pathname akan cocok dengan semua file dan nol atau lebih direktori dan subdirektori. Jika pola diikuti oleh a, hanya direktori dan subdirektori yang cocok.
**
untuk muncul kembali ke dalam subdirektori.
file
tidak selalu menentukan ekstensi itu tampaknya: itu mengubah file bash ke foo.bourne-again
sini misalnya!
Script di bawah ini dapat digunakan untuk (secara rekursif) mengganti nama ekstensi yang salah diatur .jpg
,, ke yang benar. Jika menemukan file yang tidak dapat dibaca, itu akan melaporkannya dalam output skrip.
Script menggunakan imghdr
modul, untuk mengenali jenis berikut: rgb
, gif
, pbm
, pgm
, ppm
, tiff
, rast
, xbm
, jpeg
, bmp
, png
. Lebih lanjut tentang imghdr
modul di sini . Daftar dapat diperpanjang dengan lebih banyak jenis, seperti yang disebutkan dalam tautan.
Seperti itu, ia secara khusus mengganti nama file dengan ekstensi .jpg
, sebagaimana disebutkan dalam pertanyaan. Dengan perubahan kecil, bisa cocok untuk mengubah nama ekstensi apa pun, atau serangkaian ekstensi tertentu, menjadi yang benar (atau tanpa ekstensi, seperti di sini ).
#!/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
Jalankan dengan perintah:
python3 /path/to/rename.py <directory>
Catatan: Pendekatan saya tampaknya terlalu rumit. Saya lebih suka jawaban terdon di tempat Anda.
Anda dapat menggunakan perintah file
untuk menentukan jenis 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
Dengan informasi ini, file dapat diubah namanya:
Silakan lakukan tes sebelum Anda menerapkan perintah ke gambar Anda
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)
}'
Contoh
% 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 "..."
dan lakukan segala sesuatu di sana atau gunakan while read -d '' name type
untuk membagi nama file dan file
output dan kemudian parsing $type
untuk mendapatkan tipe file. Tidak sepadan, lihat jawaban saya untuk melakukannya dengan lebih mudah di bash (ish) murni.