Bagaimana saya bisa mengganti nama foto, mengingat data EXIF?


14

Katakanlah saya memiliki banyak foto, semua dengan informasi EXIF ​​yang benar, dan foto-foto tersebut dinamai secara acak (karena masalah yang saya alami). Saya memiliki program kecil yang disebut jheadyang memberi saya output di bawah ini:

$ jhead IMG_9563.JPG

File name    : IMG_9563.JPG
File size    : 638908 bytes
File date    : 2011:02:03 20:25:09
Camera make  : Canon
Camera model : Canon PowerShot SX210 IS
Date/Time    : 2011:02:03 20:20:24
Resolution   : 1500 x 2000
Flash used   : Yes (manual)
Focal length :  5.0mm  (35mm equivalent: 29mm)
CCD width    : 6.17mm
Exposure time: 0.0080 s  (1/125)
Aperture     : f/3.1
Focus dist.  : 0.29m
ISO equiv.   : 125
Exposure bias: -1.67
Whitebalance : Manual
Light Source : Daylight
Metering Mode: pattern
Exposure Mode: Manual

Sekarang saya perlu mengganti nama semua foto di folder dalam format berikutnya:

001.JPG
002.JPG
003.JPG
...

Di mana angka minor akan menjadi gambar yang lebih tua, dan maksimum yang lebih baru.

Saya bukan skrip yang bagus, jadi saya minta bantuan.

Saya pikir skrip bash sudah cukup, tetapi jika Anda merasa lebih nyaman, Anda dapat menulis skrip python.

Saya memikirkan sesuatu seperti:

$ mv IMG_9563.JPG `jhead IMG_9563.JPG | grep date`

tapi saya tidak tahu bagaimana melakukannya untuk semua file sekaligus.


Saya tidak mengerti kalimat minor / maksimum dan contoh sebelumnya. Bisakah Anda mengklarifikasi ini?
maxschlepzig

Nama file kecil / maksimum itu satu langkah lebih maju. Karena, setelah saya memiliki file dengan nama yang mereka mewakili yang lebih tua dan lebih baru, saya dapat dengan mudah mengganti nama menjadi 001.jpg, 002.jpg, dll dengan program lain, meskipun akan lebih baik untuk melakukannya dengan skrip lain.
Tomas

"Tabel penggantian nama" akan menjadi ls *.JPG | wc > renameDan kemudian saya harus menggunakan nama skrip untuk XXX.JPG
Tomas

Sory, bukan wc, saya lupa yang memesan dengan nama.
Tomas

Perintahnya adalah sort.
Tomas

Jawaban:


10

Anda bisa melakukannya untuk semua file menggunakan for loop (di shell / di skrip shell):

for i in *.JPG; do
  j=`jhead "$i" | grep date | sed 's/^File date[^:]\+: \(.\+\)$/\1/'`.jpg
  echo mv -i "$i" "$j"
done

Ini hanya garis besar yang sangat mendasar. Hapus echoketika Anda telah memverifikasi bahwa semuanya berfungsi seperti yang diharapkan.


Terima kasih. Sekarang, tolong beri aku File date : 2011:02:03 20:25:09. Bagaimana saya bisa memfilter hanya kolom kedua?
Tomas

Jadi saya hanya mengganti nama file menjadi 20:25:09
Tomas

@ Thomas, memperbarui jawabannya - jika Anda benar-benar hanya ingin waktu (bagaimana dengan tabrakan?) Anda harus mengubah ekspresi reguler, tentu saja.
maxschlepzig

j=`jhead "$i" | grep date | sed 's/.* //'`.jpgsebagai gantinya?
frabjous

@maxshlepzig: Terima kasih, Anda melewatkan '`` .jpg` sebelumnya
Tomas

28

Baru tahu di sini bahwa jhead dapat melakukan semuanya untuk Anda! :)

jhead -autorot -nf%Y-%m-%d_%H-%M-%S *.jpg

7
Iya! Tapi hati-hati dengan string format tertentu, karena itu akan memberikan dua file yang diambil dengan nama yang sama. %i(atau %03i, secara khusus) akan memberikan nomor urut, seperti yang diminta dalam pertanyaan awal. Menggabungkan keduanya mungkin bukan ide yang buruk.
mattdm

Hanya untuk menanggapi komentar mattdm - manual '' jhead '' menunjukkan akan menambahkan angka atau huruf tambahan (1,2,3 atau a, b, c dll) ke duplikat (cap waktu identik) secara otomatis.
John U

0

Jika seseorang membutuhkan penggantian nama yang lebih kompleks, misalnya untuk memasukkan nilai eksposur kunci ke dalam nama file, inilah skrip kecil saya. Ini mengganti nama file jpeg untuk sesuatu seperti ini: NightSky_2014.08.27_22.30.05_NX20_F2.8_f20.0mm_20s_ISO800.jpg.

#!/bin/bash

for s in *.jpg *.JPG
do
 echo $s
 x=`jhead "$s" | \
 awk 'BEGIN { cmt=""; }
/Camera model/   { c=$4$5$6;} 
/Exposure time:/ { e=$3; 
                   if (e==int(e)) e=int(e); 
                   if (e<1) {e=int(0.5+1/e); e="1T" e "s";} else { e=e "s"; } 
                 }
/ISO equiv./     { iso="ISO" $4; } 
/Focal length/   { f="f" $4; } 
/Date.Time /     { d=$3 "_" $4; gsub(":",".",d); }
/Aperture /      { ap=$3; gsub("f/","F",ap); } 
/Comment  /      { cmt=$3 "_"; }
END { print cmt d "_" c "_" ap "_" f "_" e "_" iso ".jpg"; }'`

 echo mv $s $x
 mv $s $x
 echo =====
done

0

Saya menyukai kode yang diposting oleh maxschlepzig tetapi masih mengalami kesulitan dengan hasilnya.

Masalahnya adalah ruang dalam nama file yang dihasilkan (antara string tanggal dan string waktu). Sementara sepele bagi siapa pun yang menggunakan GUI, itu membuat penanganan file pada baris perintah agak lebih sulit.

Di sini perintah 'sed' secara substansial telah diubah menjadi empat operasi 'sed' terpisah yang mendukung argumen monolitik sebelumnya. Untuk menyesuaikan diri saya, berikut ini juga mengubah file ke izin 644 normal.

for i in *.JPG ; do
  chmod 644 $i
  j=`jhead "$i" | grep ^Date/Time | sed -e 's/^Date\/Time[ ]\+: //;s/:/-/g;s/ /_/g':/-/g;s/ /_/g'`.jpg
  echo mv -i "$i" "$j"
  # mv -i "$i" "$j"
done

2
Selamat datang di Stack Exchange. (1) Saya mengerti dengan sedbaik, jadi pada dasarnya saya mengerti apa yang Anda coba lakukan. Tetapi tujuan kami di Stack Exchange adalah tidak membagikan sandwich ikan atau menulis ribuan solusi satu kali untuk pertanyaan-pertanyaan yang berbeda; Tujuan kami adalah untuk mengajar orang cara memancing (yaitu, mengajar orang, termasuk penanya saat ini dan pembaca masa depan, bagaimana menyelesaikan masalah mereka sendiri). Untuk itu, jawaban Anda akan lebih baik jika Anda menjelaskan apa yang sedang Anda upayakan. (Tolong jangan menanggapi dalam komentar; edit jawaban Anda untuk membuatnya lebih jelas.) ... (Lanjutkan)
G-Man Mengatakan 'Reinstate Monica'

(Lanjutan) ... (2) Perintah Anda gagal karena tanda kutip tidak seimbang. Tolong jangan memposting kode yang belum diuji.
G-Man Mengatakan 'Reinstate Monica'

0

Karena lebih mudah untuk berurusan dengan (imho), saya menulis sendiri sebuah skrip Ruby:

require 'fileutils'

ARGV.each { |file|
  if File.exist?(file) && !File.directory?(file)
    exif = `exiftool "#{file}" | grep -E "(Error|Create Date)"`
    if exif.strip.size > 0
      exif = exif.split("\n")[0].split(/\s+/)
      if exif[0] != "Error"
        # Change the target format here
        filename = exif[3].gsub(":", "-") + " " + 
                   exif[4].gsub(":", ".") + 
                   File.extname(file)
        if filename != file && !File.exist?(filename)
          FileUtils::mv(file, File.dirname(file) + "/" + filename)
        end
      end
    end
  end
}

Apa fungsinya?

  1. Iterasikan semua file yang dilewatkan sebagai parameter (mis *.JPG.).

    Saya memeriksa apakah ia menangani file dan video RAW dengan benar. Ini harus bekerja dengan semua hal yang exiftoolbisa dilakukan.

  2. Tidak melakukan apa pun jika file

    • tidak ada,
    • adalah sebuah direktori,
    • tidak memiliki tanggal EXIF, atau
    • exiftool melaporkan kesalahan, atau
    • file dengan nama file target sudah ada.

Itu membuatnya cukup kuat. Secara khusus, tidak ada file yang dapat menghilang (secara diam-diam) seperti halnya dengan beberapa jawaban lainnya.


0

exiv2 akan menjadi alternatif untuk memanipulasi, yang memungkinkan sintaks yang sangat sederhana:

exiv2 adalah program untuk membaca dan menulis komentar Exif, IPTC, XMP dan gambar dan dapat membaca banyak tag pembuat makernote. Program ini secara opsional mengkonversi antara tag Exif, properti XMP dan dataset IPTC

Jadi ini akan mengganti nama semua jpeg di folder saat ini:

for i in *.JPG; do exiv2 -v -r '%Y%m%d.%H%M%S.:basename:' rename "$i"; done

Jika Anda juga ingin menambahkan informasi geo, Anda dapat menggunakan exivtool:

exiftool '-filename<${gpslatitude;} ${gpslongitude} ${datetimeoriginal}' -d "%Y-%m-%d %H.%M.%S%%-c.%%e" *.JPG

0

Saya suka solusi @Vinvin, karena saya ingin menjaga nama asli juga (menghindari masalah dengan gambar yang diambil pada detik yang sama), ini dia solusi saya:

for i in *.JPG; do jhead -nf%Y%m%d_%H%M%S_"$(basename "$i" .JPG)" "$i" ; done

0

Posting pertama oleh pemula ... Skrip bash pertama ... Saya menyukai solusi Libor / HalosGhost di atas karena menyertakan rincian lebih lanjut dalam penggantian nama. Tetapi setelah pengujian, nama file duplikat akan berakhir kehilangan file. Jadi saya menambahkan tag penghitung ke akhir nama file untuk referensi dan pencegahan tabrakan yang mudah. Saya yakin seseorang di sini dapat memperbaiki ini tetapi berpikir itu mungkin membantu.

Saya minta maaf memposting kode. Saya mengalami kesulitan dengan antarmuka tetapi jika seseorang dapat mengarahkan saya ke cara yang benar dalam melakukan sesuatu, itu akan bagus.

#!/bin/bash

y=1
for s in *.jpg *.JPG
do
 echo $s
 x=`jhead "$s" | \
 awk 'BEGIN { cmt=""; }
/Camera model/   { c=$4$5$6;}
/Exposure time:/ { e=$3;
                   if (e==int(e)) e=int(e);
                   if (e<1) {e=int(0.5+1/e); e="1T" e "s";} else { e=e "s"; }
                 }
/ISO equiv./     { iso="ISO" $4; }
/Focal length/   { f="f" $4; }
/Date.Time /     { d=$3 "_" $4; gsub(":","",d); }
/Aperture /      { ap=$3; gsub("f/","F",ap); }
/Comment  /      { cmt=$3 "_"; }
END { print cmt d "_" c "_" ap "_" f "_" e "_" iso "_" ; }'`

 echo mv $s "$x${y}.jpg"
 mv $s "$x${y}.jpg"
 y=$((y+1))
 echo =====
done

Terima kasih Stephen untuk hasil editnya. Mencoba belajar
jgroezin
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.