Doğru dosya uzantıları


15

Farklı dosya türlerinde yaklaşık 12000 görüntüm var, ancak her biri * .jpg olarak yeniden adlandırıldı.

Şimdi onlara uygun uzantılarını geri vermek istiyorum, nasıl yapabilirim


2
özyinelemeli mi, yoksa "düz" bir dizinde mi?
Jacob Vlijm


1
@steeldriver oldukça yakın, ancak bu dosyaların don değil bir uzantıya sahip, burada sahip oldukları yanlış uzantısı.
Jacob Vlijm

1
@JacobVlijm bu yüzden soruyu yinelenen olarak işaretlemedim: ancak cevaplarda önerilen yöntemlerin değeri var, IMHO
steeldriver 19

@steeldriver Tamamen katılıyorum.
Jacob Vlijm

Yanıtlar:


22

Bunu bash'da nispeten kolayca yapabilirsiniz:

for f in *jpg; do 
    type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+') 
    mv "$f" "${f%%.*}.${type,,}"  
done

Bu, @ AB'nin cevabı ile aynı fikirdir, ancak bunun yerine kabuk globları kullanmaktır find. ${f%%.*}Onun uzantısı olmadan dosya adıdır. -0Arasında filekomuta bir baskı yapar \0o zaman için kullandığınız dosya adından sonra grepdosya türü. Bu, boşluk, yeni satır veya başka bir şey içerenler de dahil olmak üzere rastgele dosya adlarıyla çalışmalıdır. Küçük ${type,,}harf uzantıları almak için bir hile. Bu dönüştürmek istiyorum PNGiçin png.

Sorunuzda söylemediniz, ancak bunun yinelemeli olması ve alt dizinlere inmesi gerekiyorsa, bunun yerine bunu kullanabilirsiniz:

shopt -s globstar
for f in **/*jpg; do 
    type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+') 
    mv "$f" "${f%%.*}.${type,,}"  
done

shopt -s globstarSağlayan Bash'in globstar seçeneğini sağlayacak **maç alt dizinleri:

globstar

Ayarlanırsa, yol adı genişletme bağlamında kullanılan model ** tüm dosyalarla ve sıfır veya daha fazla dizin ve alt dizinle eşleşir. Deseni bir / izliyorsa, yalnızca dizinler ve alt dizinler eşleşir.


@AB güncellemeye bakın. Alt **dizinlere geri dönmeye izin verir .
terdon

Her satırın sonundaki noktalı virgüller gereksizdir, değil mi?
Paddy Landau

@PaddyLandau evet, tek bir astar olarak test ediyordum ve netlik için yeni satırlar ekledim. Onları kaldırmayı unuttum. Yanlış olmadığını, söylediğiniz gibi gereksiz olduğunu unutmayın.
terdon

Harika, her filezaman uzantıyı belirtmese de: foo.bourne-againörneğin bir bash dosyasını buraya dönüştürüyor !
Campa

1
@Kampa hayır, elbette hayır. Ayrıca ikili dosyalara, normal metin dosyalarına, perl ve python komut dosyalarına sahte uzantılar ekler ve liste devam eder. Soru özellikle resimler hakkında soruyordu ve bunlar normal uzantılarıyla aynı ada sahip olma eğilimindeydi. Linux'taki uzantıların isteğe bağlı olduğunu, çok az istisna dışında, aslında hiçbir şey yapmadığını unutmayın. Kullanıcının verilerini düzenlemesine yardımcı olurlar, işletim sistemi onları umursamaz.
terdon

11

Aşağıdaki komut dosyası, yanlış ayarlanmış bir uzantıyı (yinelemeli olarak) doğru olana yeniden adlandırmak için kullanılabilir .jpg. Okunamayan bir dosya bulursa, dosyayı komut dosyasının çıktısında bildirir.

Komut kullanmak imghdraşağıdaki türde tanımak, modül: rgb, gif, pbm, pgm, ppm, tiff, rast, xbm, jpeg, bmp, png. Buradaimghdr modül hakkında daha fazla bilgi . Liste, bağlantıda belirtildiği gibi daha fazla türde genişletilebilir.

Olduğu gibi, özellikle .jpgsoruda belirtildiği gibi uzantıya sahip dosyaları yeniden adlandırır . Küçük bir değişiklikle, herhangi bir uzantıyı veya belirli bir uzantı grubunu doğru olana yeniden adlandırmak uygun olabilir (veya burada olduğu gibi uzantı içermez ).

Senaryo:

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

Nasıl kullanılır

  1. Komut dosyasını boş bir dosyaya kopyalayın, rename.py
  2. Komut ile çalıştırın:

    python3 /path/to/rename.py <directory>
    

Bash tabanlı çözümlerin aksine basit ve okunması kolay +1.
Davide

3

Not: Yaklaşımım çok karmaşık görünüyor. Yerinizde terdons cevabını tercih ederim.


fileDosya türünü belirlemek için komutu kullanabilirsiniz :

% 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

Bu bilgilerle dosyalar yeniden adlandırılabilir:

Komutu resimlerinize uygulamadan önce lütfen bir test yapın

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)
   }'

Misal

% 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

Bu durumun, dosya adlarından herhangi birinin satırsonu içermesi durumunda ortaya çıkacağını unutmayın.
terdon

@terdon Evet, düşünüyordum. Ne yazık ki ne yapabileceğim hakkında hiçbir fikrim yok. Yardım edebilir misin?
AB

Ben awk kullanarak bunu düzgün yapmak için hiçbir fikrim yok. Bu iş için doğru araç değil. Ya find -exec bash -c "..."orada her şeyi kullanın ve yapın ya while read -d '' name typeda dosya adını ve fileçıktısını bölmek ve sonra $typedosya türünü almak için ayrıştırmak için kullanın. Gerçekten buna değmez, saf (ish) bash'da nasıl daha kolay yapılacağına dair cevabımı görün.
terdon
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.