Phần mở rộng tập tin đúng


16

Tôi có khoảng 12000 hình ảnh thuộc các loại tệp khác nhau nhưng mỗi một trong số chúng đã được đổi tên thành * .jpg.

Bây giờ tôi muốn cung cấp cho họ phần mở rộng thích hợp của họ trở lại, làm thế nào tôi có thể làm điều đó


2
đệ quy, hoặc trong một thư mục "phẳng"?
Jacob Vlijm


1
@steel ấn khá gần, nhưng những tệp đó không có phần mở rộng, ở đây chúng có phần mở rộng sai .
Jacob Vlijm

1
@JacobVlijm đó là lý do tại sao tôi không gắn cờ câu hỏi là trùng lặp: tuy nhiên các phương pháp được đề xuất trong câu trả lời có giá trị ở đây, IMHO
Steeldo

@steel ấn Tôi hoàn toàn đồng ý.
Jacob Vlijm

Câu trả lời:


23

Bạn có thể làm điều đó tương đối dễ dàng trong bash:

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

Đây là ý tưởng tương tự như câu trả lời của @ AB nhưng sử dụng các khối vỏ thay vì find. Tên ${f%%.*}tệp không có phần mở rộng của nó. Các -0của filelệnh làm cho nó in một \0sau tên tập tin mà chúng tôi sau đó sử dụng để greploại tệp. Điều này sẽ làm việc với các tên tệp tùy ý, bao gồm cả các tên có chứa khoảng trắng, dòng mới hoặc bất cứ thứ gì khác. Đây ${type,,}là một mẹo để có được phần mở rộng trường hợp thấp hơn. Nó sẽ chuyển đổi PNGthành png.

Bạn đã không nói trong câu hỏi của mình, nhưng nếu bạn cần điều này để đệ quy và chuyển sang thư mục con, bạn có thể sử dụng điều này thay thế:

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

Các shopt -s globstarsẽ kích hoạt tùy chọn globstar bash của cho phép **các thư mục con phù hợp:

sao

Nếu được đặt, mẫu ** được sử dụng trong ngữ cảnh mở rộng tên đường dẫn sẽ khớp với tất cả các tệp và không hoặc nhiều thư mục và thư mục con. Nếu mẫu được theo sau bởi /, chỉ các thư mục và thư mục con phù hợp.


@AB xem cập nhật. Nó cho phép **tái diễn vào các thư mục con.
terdon

Những dấu chấm phẩy ở cuối mỗi dòng là dư thừa, phải không?
Paddy Landau

@PaddyLandau vâng, tôi đã thử nghiệm nó như một lớp lót và thêm các dòng mới cho rõ ràng ở đây. Tôi quên loại bỏ chúng. Lưu ý rằng họ không sai, chỉ thừa như bạn nói.
terdon

Tuyệt vời, mặc dù filekhông phải lúc nào cũng chỉ định phần mở rộng có vẻ như: chẳng hạn, nó biến một tệp bash thành foo.bourne-againở đây!
Campa

1
@Campa không, tất nhiên là không. Nó cũng sẽ thêm các phần mở rộng không có thật vào các tệp nhị phân, các tệp văn bản thông thường, các tập lệnh perl và python và danh sách sẽ tiếp tục. Câu hỏi được hỏi về hình ảnh cụ thể và những hình ảnh có xu hướng có cùng tên với phần mở rộng thông thường của chúng. Hãy nhớ rằng các tiện ích mở rộng trên Linux là tùy chọn, với rất ít ngoại lệ, chúng thực sự không làm gì cả. Họ giúp người dùng sắp xếp dữ liệu của họ, HĐH không quan tâm đến họ.
terdon

11

Tập lệnh bên dưới có thể được sử dụng để (đệ quy) đổi tên một phần mở rộng được đặt không chính xác, thành phần mở rộng .jpgchính xác. Trong trường hợp nó tìm thấy một tập tin không thể đọc được, nó sẽ báo cáo nó trong đầu ra của tập lệnh.

Các kịch bản sử dụng các imghdrmô-đun, để nhận ra các loại sau: rgb, gif, pbm, pgm, ppm, tiff, rast, xbm, jpeg, bmp, png. Thêm về các imghdrmô-đun ở đây . Danh sách có thể được mở rộng với nhiều loại hơn, như được đề cập trong liên kết.

Như nó là, nó đặc biệt đổi tên các tập tin với phần mở rộng .jpg, như được đề cập trong câu hỏi. Với một thay đổi nhỏ, có thể phù hợp để đổi tên bất kỳ tiện ích mở rộng hoặc một bộ tiện ích mở rộng cụ thể nào thành một tiện ích mở rộng chính xác (hoặc không có tiện ích mở rộng, như ở đây ).

Kịch bản:

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

Cách sử dụng

  1. Sao chép tập lệnh vào một tập tin trống, lưu nó dưới dạng rename.py
  2. Chạy nó bằng lệnh:

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

+1 cho đơn giản và dễ đọc, không giống như các giải pháp dựa trên bash.
Davide

3

Lưu ý: Cách tiếp cận của tôi dường như quá phức tạp. Tôi muốn trả lời terdons ở vị trí của bạn.


Bạn có thể sử dụng lệnh fileđể xác định loại tệp:

% 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

Với thông tin này, các tập tin có thể được đổi tên:

Vui lòng kiểm tra trước khi bạn áp dụng lệnh cho hình ảnh của bạ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)
   }'

Thí dụ

% 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

Lưu ý rằng điều này sẽ phá vỡ trong trường hợp không chắc là bất kỳ tên tệp nào chứa dòng mới.
terdon

@terdon Vâng, tôi đã suy nghĩ. Thật không may, tôi không biết tôi có thể làm gì. Bạn có thể giúp?
AB

Tôi không có ý tưởng làm thế nào để làm điều này đúng cách sử dụng awk. Nó không phải là công cụ phù hợp cho công việc. Sử dụng find -exec bash -c "..."và làm mọi thứ trong đó hoặc sử dụng while read -d '' name typeđể phân tách tên tệp và fileđầu ra, sau đó phân tích cú pháp $typeđể lấy loại tệp. Thực sự không đáng, hãy xem câu trả lời của tôi để biết cách thực hiện dễ dàng hơn nhiều trong bash thuần túy (ish).
terdon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.