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 đó
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 đó
Câu trả lời:
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 -0
của file
lệnh làm cho nó in một \0
sau tên tập tin mà chúng tôi sau đó sử dụng để grep
loạ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 PNG
thà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 globstar
sẽ 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.
**
tái diễn vào các thư mục con.
file
khô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!
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 .jpg
chí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 imghdr
mô-đ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 imghdr
mô-đ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 ).
#!/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)
rename.py
Chạy nó bằng lệnh:
python3 /path/to/rename.py <directory>
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
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).