EXIF verileri göz önüne alındığında fotoğrafları nasıl yeniden adlandırabilirim?


14

Diyelim ki hepsi doğru EXIF ​​bilgisine sahip bir grup fotoğrafım var ve fotoğraflar rastgele adlandırıldı (sahip olduğum bir sorun nedeniyle). jheadAşağıdaki çıktı verir bana denilen küçük bir program var :

$ 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

Şimdi klasördeki tüm fotoğrafları bir sonraki formatta yeniden adlandırmam gerekiyor:

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

Küçük sayının eski görüntü, maksimum sayı daha yeni olacağı yer.

Çok iyi senaryo yazmıyorum, bu yüzden yardım istiyorum.

Bence bir bash betiği yeterli, ama daha rahat hissediyorsanız, bir python betiği yazabilirsiniz.

Gibi bir şey düşündüm:

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

ancak bunu tüm dosyalar için bir kerede nasıl yapacağımı bilmiyorum.


Küçük / azami cümleyi ve önceki örneği anlamıyorum. Bunu açıklığa kavuşturabilir misiniz?
maxschlepzig

Bu küçük / maksimum dosya adları bir adım ileri gider. Çünkü, daha eski ve daha yeni olan bir şekilde adlandırılmış dosyaları adlandırdığımda, başka bir programla yapmak daha iyi olsa da, 001.jpg, 002.jpg, vb.
Tomas

"Yeniden adlandırma tablosu" olurdu ls *.JPG | wc > renameVe sonra XXX.JPG için bir komut dosyası yeniden adlandırma kullanmak zorunda kalacak
Tomas

Sory, değil wc, adıyla sipariş vermeyi unuttum.
Tomas

Komut sıralamadır.
Tomas

Yanıtlar:


10

For döngüsü kullanarak tüm dosyalar için bunu yapabilirsiniz (kabukta / kabuk komut dosyasında):

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

Bu sadece çok basit bir taslak. echoHer şeyin beklendiği gibi çalıştığını doğruladıktan sonra silin .


Teşekkürler. Şimdi, grep woudl ver File date : 2011:02:03 20:25:09. Yalnızca ikinci sütunu nasıl filtreleyebilirim?
Tomas

Bu yüzden dosyayı sadece 20:25:09 olarak değiştirdim
Tomas

@Tomas, cevabı güncelledi - gerçekten sadece zamanı istiyorsanız (çarpışmalar ne olacak?), Normal ifadeyi değiştirmek zorundasınız elbette.
maxschlepzig

j=`jhead "$i" | grep date | sed 's/.* //'`.jpgyerine?
Şahane

@maxshlepzig: Teşekkürler, '`` .jpg`'den önce kaçırdınız
Tomas

29

Sadece burada jhead sizin için her şeyi yapabilir öğrendim! :)

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

7
Evet! Ancak bu belirli biçim dizesine dikkat edin, çünkü aynı saniyede aynı adı taşıyan iki dosya verecektir. %i(veya %03iözellikle) orijinal soruda istendiği gibi bir sıra numarası verecektir. Her ikisini birleştirmek kötü bir fikir olmayabilir.
mattdm

Sadece mattdm'in yorumuna yanıt vermek için - '' jhead '' kılavuzu, kopyalara (özdeş zaman damgası) otomatik olarak fazladan bir sayı veya harf (1,2,3 veya a, b, c vb.) Ekleyeceğini önerir.
John U

0

Birisi daha karmaşık yeniden adlandırmaya ihtiyaç duyarsa, örneğin dosya adına anahtar pozlama değerlerini dahil etmek için, benim küçük komut dosyam. Böyle bir şey jpeg dosyaları yeniden adlandırır: 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

Ben maxschlepzig tarafından yayınlanan kodu sevdim ama yine de çıktı ile ilgili zorluklar vardı.

Sorun, sonuçtaki dosya adındaki (tarih dizesi ve saat dizesi arasındaki) boşluktu. GUI kullanan herkes için önemsiz olmakla birlikte, komut satırında dosya işlemeyi biraz daha zorlaştırır.

Burada 'sed' komutu büyük ölçüde önceki monolitik argüman lehine dört ayrı 'sed' işlemine dönüştürülmüştür. Kendime uyması için aşağıdakiler de dosyayı normal 644 izinlerine değiştirir.

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
Stack Exchange'e hoş geldiniz. (1) sedOldukça iyi anlıyorum , bu yüzden temelde ne yapmaya çalıştığınızı anlıyorum. Ancak Stack Exchange'deki hedefimiz, balık sandviçleri dağıtmak veya önemsiz derecede farklı sorulara binlerce tek seferlik çözüm yazmak değil; amacımız insanlara balık tutmayı öğretmektir (yani, mevcut soru soran ve gelecekteki okuyucular da dahil olmak üzere insanlara kendi sorunlarını nasıl çözeceklerini öğretmek). Bu amaçla, çabaladığınızı açıklarsanız cevabınız daha iyi olurdu. (Lütfen yorumlarda yanıt vermeyin; daha açık hale getirmek için cevabınızı düzenleyin .)… (Devam ediyor)
G-Man, 'Monica'yı Yeniden Başlat' diyor

(Devam)… (2) Tırnaklar dengeli olmadığından komutunuz başarısız oluyor. Lütfen denenmemiş kod göndermeyin.
G-Man '

0

(İmho) ile başa çıkmak daha kolay olduğu için kendime bir Ruby senaryosu yazdım:

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
}

Bu ne yapar?

  1. Parametre olarak geçirilen tüm dosyalar üzerinde tekrarlar (örn. *.JPG).

    RAW dosya ve videolarını doğru şekilde işlediğini kontrol ettim. Her şeyle çalışmalıexiftool başa çıkabilir.

  2. Bir dosya varsa hiçbir şey yapmaz

    • bulunmuyor,
    • bir dizin,
    • EXIF tarihi yok veya
    • exiftool bir hata bildirir veya
    • hedef dosya adına sahip bir dosya zaten var.

Bu onu oldukça sağlam yapar. Özellikle, diğer cevapların bazılarında olduğu gibi hiçbir dosya yok olmaz (sessizce).


0

exiv2 çok basit bir sözdizimine izin veren, manipülasyon için bir alternatif olacaktır:

exiv2, Exif, IPTC, XMP meta verileri ve görüntü yorumlarını okumak ve yazmak için kullanılan bir programdır ve birçok satıcı makernote etiketini okuyabilir. Program isteğe bağlı olarak Exif etiketleri, XMP özellikleri ve IPTC veri kümeleri arasında dönüştürme yapar

Bu, geçerli klasördeki tüm jpegleri yeniden adlandırır:

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

Coğrafi bilgiler de eklemek istiyorsanız, aşağıdakileri kullanabilirsiniz exivtool:

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

0

@ Kevin'in çözümünü seviyorum, çünkü orijinal adı da tutmak istedim (aynı saniyede çekilen görüntülerde sorundan kaçınmak), işte benim çözümüm:

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

0

Yeni başlayan tarafından ilk yazı ... İlk bash script ... Yeniden adlandırmada daha fazla ayrıntı içerdiği için yukarıdaki Libor / HalosGhost çözümünü beğendim. Ancak test ettikten sonra, yinelenen dosya adları dosyaları kaybeder. Bu yüzden kolay başvuru ve çarpışma önleme için dosya adının sonuna bir sayaç etiketi ekledim. Eminim buradaki biri bu konuda düzelebilir ama bunun yardımcı olabileceğini düşündüm.

Kodu özür dilerim. Arayüzle ilgili zorluklar yaşıyorum, ancak biri beni bir şeyleri doğru şekilde göstermeye yönlendirebilirse, bu harika olurdu.

#!/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

Düzenleme için Stephen'a teşekkür ederim. Öğrenmeye çalışıyor
jgroezin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.