นามสกุลไฟล์ที่ถูกต้อง


15

ฉันมีรูปแบบไฟล์ต่างกันประมาณ 12,000 รูป แต่รูปทุกรูปเปลี่ยนเป็น * .jpg

ตอนนี้ฉันต้องการให้ส่วนขยายที่เหมาะสมกลับคืนมาฉันจะทำอย่างไร


2
ซ้ำหรือในไดเรกทอรี "แบน"?
Jacob Vlijm


1
@steeldriver อยู่ใกล้ ๆ แต่ไฟล์เหล่านั้นไม่มีส่วนขยายที่นี่พวกเขามีส่วนขยายที่ไม่ถูกต้อง
Jacob Vlijm

1
@JacobVlijm นั่นเป็นเหตุผลที่ฉันไม่ได้ตั้งค่าสถานะคำถามซ้ำ: อย่างไรก็ตามวิธีการที่เสนอในคำตอบมีความคุ้มค่าที่นี่ IMHO
steeldriver

@steeldriver ฉันเห็นด้วยอย่างสมบูรณ์
Jacob Vlijm

คำตอบ:


22

คุณสามารถทำได้ง่ายๆในการทุบตี:

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

นี่คือความคิดเช่นเดียวกับคำตอบ @ AB แต่ใช้เปลือก globs findแทน ${f%%.*}เป็นชื่อไฟล์โดยไม่มีนามสกุลของตน -0ของfileคำสั่งที่ทำให้มันพิมพ์\0หลังจากชื่อไฟล์ที่เรานั้นใช้grepประเภทของไฟล์ สิ่งนี้ควรทำงานกับชื่อไฟล์โดยพลการรวมถึงชื่อที่มีช่องว่างการขึ้นบรรทัดใหม่หรือสิ่งอื่นใด นี่${type,,}เป็นเคล็ดลับในการรับส่วนขยายตัวพิมพ์เล็ก มันจะเปลี่ยนไปPNGpng

คุณไม่ได้พูดในคำถามของคุณ แต่ถ้าคุณต้องการสิ่งนี้เพื่อเรียกซ้ำและสืบสู่ไดเรกทอรีย่อยคุณสามารถใช้สิ่งนี้แทน:

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 globstarจะเปิดใช้ตัวเลือก GLOBSTAR ทุบตีซึ่งช่วยให้**ไดเรกทอรีย่อยการแข่งขัน:

GLOBSTAR

หากตั้งค่ารูปแบบ ** ที่ใช้ในบริบทการขยายชื่อพา ธ จะจับคู่ไฟล์ทั้งหมดและไดเรกทอรีหรือไดเรกทอรีย่อยเป็นศูนย์หรือมากกว่า หากรูปแบบตามด้วย / เฉพาะไดเรกทอรีและไดเรกทอรีย่อยที่ตรงกัน


@AB ดูการอัปเดต ช่วยให้**สามารถเรียกเก็บเงินคืนในไดเรกทอรีย่อย
terdon

อัฒภาคเหล่านั้นที่ส่วนท้ายของแต่ละบรรทัดซ้ำซ้อนใช่ไหม
Paddy Landau

@PaddyLandau ใช่ฉันกำลังทดสอบมันเป็นหนึ่งซับและเพิ่มบรรทัดใหม่เพื่อความชัดเจนที่นี่ ฉันลืมที่จะลบพวกเขา โปรดทราบว่าพวกเขาไม่ผิดเพียงแค่ซ้ำซ้อนตามที่คุณพูด
terdon

เยี่ยมมากแม้ว่าจะfileไม่ได้ระบุนามสกุล แต่อย่างใด: มันเปลี่ยนไฟล์ทุบตีเป็นfoo.bourne-againตัวอย่าง!
Campa

1
@Campa ไม่แน่นอนไม่ นอกจากนี้ยังจะเพิ่มส่วนขยายปลอมไปยังไฟล์ไบนารีไฟล์ข้อความปกติสคริปต์ Perl และงูหลามและรายการไปที่ คำถามที่ถามเกี่ยวกับภาพโดยเฉพาะและผู้ที่มีแนวโน้มที่จะมีชื่อเดียวกันกับนามสกุลปกติของพวกเขา โปรดจำไว้ว่าส่วนขยายบน Linux นั้นเป็นทางเลือกโดยที่มีข้อยกเว้นน้อยมากพวกมันไม่ได้ทำอะไรเลย พวกเขาช่วยให้ผู้ใช้จัดระเบียบข้อมูลของพวกเขาระบบปฏิบัติการไม่สนใจพวกเขา
terdon

11

สคริปต์ด้านล่างสามารถใช้ไป (ซ้ำ) เปลี่ยนชื่อนามสกุลตั้งไม่ถูกต้อง.jpgในการที่ถูกต้อง ในกรณีที่พบไฟล์ที่ไม่สามารถอ่านได้มันจะรายงานในเอาต์พุตของสคริปต์

สคริปต์ที่ใช้imghdrโมดูลที่จะรับรู้ประเภทต่อไปนี้: rgb, gif, pbm, pgm, ppm, tiff, rast, xbm, jpeg, ,bmp pngเพิ่มเติมเกี่ยวกับimghdrโมดูลที่นี่ รายการสามารถขยายได้ด้วยประเภทอื่น ๆ ตามที่กล่าวไว้ในลิงค์

เนื่องจากมันเป็นเฉพาะการเปลี่ยนชื่อไฟล์ที่มีนามสกุล.jpgตามที่กล่าวไว้ในคำถาม ด้วยการเปลี่ยนแปลงเล็กน้อยสามารถเปลี่ยนชื่อส่วนขยายใด ๆ หรือชุดของส่วนขยายเฉพาะให้เป็นส่วนเสริมที่ถูกต้อง (หรือไม่มีส่วนขยายเช่นที่นี่ )

บท:

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

วิธีใช้

  1. คัดลอกสคริปต์ลงในไฟล์ว่างแล้วบันทึกเป็น rename.py
  2. เรียกใช้โดยคำสั่ง:

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

+1 สำหรับการอ่านที่ง่ายและไม่เหมือนโซลูชั่น bash based
Davide

3

หมายเหตุ: วิธีการของฉันดูเหมือนจะซับซ้อนเกินไป ฉันต้องการคำตอบ terdons ในสถานที่ของคุณ


คุณสามารถใช้คำสั่ง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

ด้วยข้อมูลนี้ไฟล์สามารถเปลี่ยนชื่อ:

กรุณาทำการทดสอบก่อนที่คุณจะใช้คำสั่งกับภาพของคุณ

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 -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

โปรดทราบว่าสิ่งนี้จะแตกในกรณีที่ไม่น่าเป็นไปได้ว่าชื่อไฟล์ใด ๆ มีการขึ้นบรรทัดใหม่
terdon

@terdon ใช่ฉันกำลังคิดอยู่ น่าเสียดายที่ฉันไม่รู้ว่าฉันสามารถทำอะไรได้ คุณช่วยได้ไหม
AB

ฉันไม่รู้ว่าจะทำอย่างไรให้ถูกต้องโดยใช้ awk มันไม่ใช่เครื่องมือที่เหมาะสมสำหรับงาน ใช้find -exec bash -c "..."และทำทุกอย่างในนั้นหรือใช้while read -d '' name typeเพื่อแยกชื่อไฟล์และfileเอาท์พุทแล้วแยกวิเคราะห์$typeเพื่อรับชนิดไฟล์ ไม่คุ้มค่าจริงๆดูคำตอบของฉันสำหรับวิธีการที่จะทำได้ง่ายขึ้นในทุบตีบริสุทธิ์
terdon
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.