Làm cách nào để đổi tên hàng loạt tệp bằng mã hóa không hợp lệ hoặc thay thế hàng loạt ký tự được mã hóa không hợp lệ?


15

Tôi có một máy chủ debian và tôi đang lưu trữ nhạc cho một đài phát thanh internet. Tôi gặp rắc rối với tên tệp và đường dẫn vì rất nhiều tệp có mã hóa không hợp lệ, ví dụ:

./music/Bändname - Some Title - additional Info/B�ndname - 07 - This Title Is Cörtain, The EncÃding Not.mp3

Lý tưởng nhất, tôi muốn xóa tất cả mọi thứ không phải là chữ cái A-Z/ a-zhoặc số 0-9hoặc dấu gạch ngang -/ gạch dưới _... Kết quả sẽ trông giống như thế:

./music/Bndname-SomeTitle-additionalInfo/Bndname-07-ThisTitleIsCrtain,TheEncdingNot.mp3

Làm thế nào để đạt được điều này cho một loạt các tập tin và thư mục?

Tôi đã thấy câu hỏi tương tự này: đổi tên hàng loạt (hoặc hiển thị chính xác) các tệp có ký tự đặc biệt

Nhưng điều này chỉ sửa lỗi mã hóa, tôi thích cách tiếp cận chặt chẽ hơn như mô tả ở trên.

Câu trả lời:


14

Bạn sẽ chạy trong một số vấn đề nếu bạn muốn đổi tên tập tin thư mục cùng một lúc. Đổi tên chỉ là một tập tin là đủ dễ dàng. Nhưng bạn muốn chắc chắn rằng các thư mục cũng được đổi tên. Bạn không thể đơn giản mv Motörhead/Encöding Motorhead/EncodingMotorheadsẽ không tồn tại tại thời điểm cuộc gọi.

Vì vậy, chúng ta cần duyệt qua chiều sâu của tất cả các tệp và thư mục, sau đó chỉ đổi tên tệp hoặc thư mục hiện tại. Phần sau hoạt động với GNU findvà Bash 4.2.42 trên OS X của tôi.

#!/usr/bin/env bash
find "$1" -depth -print0 | while IFS= read -r -d '' file; do
  d="$( dirname "$file" )"
  f="$( basename "$file" )"
  new="${f//[^a-zA-Z0-9\/\._\-]/}"
  if [ "$f" != "$new" ]      # if equal, name is already clean, so leave alone
  then
    if [ -e "$d/$new" ]
    then
      echo "Notice: \"$new\" and \"$f\" both exist in "$d":"
      ls -ld "$d/$new" "$d/$f"
    else
      echo mv "$file" "$d/$new"      # remove "echo" to actually rename things
    fi
  fi
done

Bạn có thể thay đổi regex bằng cách sử dụng new="${f//[\\\/\:\*\?\"<>|]/}"nếu bạn muốn thay thế bất cứ điều gì Windows không thể xử lý.

Lưu tập lệnh này như rename.sh, làm cho nó thực thi với chmod +x rename.sh. Sau đó, gọi nó như thế nào rename.sh /some/path.

Đảm bảo giải quyết mọi va chạm về tên tệp ( Noticethông báo của Gabriel).

Nếu bạn hoàn toàn chắc chắn rằng nó thực hiện thay thế đúng, hãy xóa đoạn mã echokhỏi tập lệnh để thực sự đổi tên mọi thứ thay vì chỉ in những gì nó làm.

Để an toàn, trước tiên tôi khuyên bạn nên thử nghiệm điều này trên một tập hợp nhỏ các tệp.


Tùy chọn giải thích

Để giải thích những gì diễn ra ở đây:

  • -depthsẽ đảm bảo các thư mục được đệ quy theo chiều sâu, vì vậy chúng tôi có thể "cuộn" mọi thứ từ cuối. Thông thường, di findchuyển khác nhau (nhưng không phải chiều rộng đầu tiên).
  • -print0đảm bảo findđầu ra là null được phân định, vì vậy chúng tôi có thể đọc nó bằng read -d ''vào filebiến. Làm như vậy giúp chúng ta xử lý tất cả các loại tên tệp lạ, bao gồm cả tên có dấu cách và thậm chí cả dòng mới.
  • Chúng tôi sẽ nhận được thư mục của tập tin với dirname. Đừng quên luôn luôn trích dẫn các biến của bạn một cách chính xác, nếu không, bất kỳ đường dẫn nào có khoảng trắng hoặc ký tự toàn cầu sẽ phá vỡ tập lệnh này.
  • Chúng tôi sẽ nhận được tên tệp thực tế (hoặc tên thư mục) với basename.
  • Sau đó, chúng tôi xóa bất kỳ ký tự không hợp lệ nào khỏi $fviệc sử dụng các khả năng thay thế chuỗi của Bash. Không hợp lệ có nghĩa là bất cứ điều gì không phải là chữ thường hoặc chữ hoa, chữ số, dấu gạch chéo ( \/), dấu chấm ( \.), dấu gạch dưới hoặc dấu gạch nối.
  • Nếu $fđã sạch (tên được làm sạch giống với tên hiện tại), hãy bỏ qua nó.
  • Nếu $newđã tồn tại trong thư mục $d(ví dụ: bạn có các tệp có tên resumerésumétrong cùng thư mục), hãy đưa ra cảnh báo. Bạn không muốn đổi tên nó, bởi vì, trên một số hệ thống, mv foo foogây ra sự cố. Nếu không thì,
  • Cuối cùng chúng tôi đổi tên tập tin gốc (hoặc thư mục) thành tên mới của nó

Vì điều này sẽ chỉ hành động theo thứ bậc sâu nhất, nên việc đổi tên Motörhead/Encödingthành Motorhead/Encodingđược thực hiện theo hai bước:

  1. mv Motörhead/Encöding Motörhead/Encoding
  2. mv Motörhead Motorhead

Điều này đảm bảo tất cả các thay thế được thực hiện theo đúng thứ tự.


Tệp ví dụ và chạy thử

Giả sử một số tệp trong thư mục cơ sở có tên test:

test
test/Motörhead
test/Motörhead/anöther_file.mp3
test/Motörhead/Encöding
test/Randöm
test/Täst
test/Täst/Töst
test/with space
test/with-hyphen.txt
test/work
test/work/resume
test/work/résumé
test/work/schedule

Đây là đầu ra từ một lần chạy trong chế độ gỡ lỗi (với echophía trước mv), tức là các lệnh sẽ được gọi và cảnh báo va chạm:

mv test/Motörhead/anöther_file.mp3 test/Motörhead/another_file.mp3
mv test/Motörhead/Encöding test/Motörhead/Encoding
mv test/Motörhead test/Motorhead
mv test/Randöm test/Random
mv test/Täst/Töst test/Täst/Tost
mv test/Täst test/Tast
mv test/with space test/withspace
Notice: "resume" and "résumé" both exist in test/work:
-rw-r—r--  …  …  test/work/resume
-rw-r—r--  …  …  test/work/résumé

Chú ý sự vắng mặt của các thông điệp cho with-hyphen.txt, scheduletestchính nó.


1
Bạn có thể muốn thêm logic để xử lý trường hợp đích mvđã tồn tại, điều này có thể xảy ra (1) nếu bạn có các tệp đã sạch (kết quả là mv foo foo) hoặc (2) nếu bạn có các tệp có cùng tên ngoại trừ cho các ký tự đặc biệt (ví dụ: mv Encöding Encodingnơi bạn đã có Encodingtệp ngoài Encöding).
Scott

Ý kiến ​​hay, cảm ơn. Bất kỳ đề xuất cụ thể về những gì để làm trong trường hợp đó? Cấp - đạt được điều này một cách sạch sẽ và lành mạnh khó hơn lúc đầu. Nếu bạn có một cái gì đó, hãy thoải mái chỉnh sửa tất nhiên.
slhck

Tôi không tin sẽ có ý nghĩa khi nghĩ về việc xử lý các va chạm tự động, chỉ cần xác định chúng với người dùng và để anh ta xử lý chúng. Tôi đã chỉnh sửa câu trả lời của bạn, như bạn đề xuất.
Scott

+1 để sử dụng ví dụ với "Encöding" Quá nhiều fon! :-)
Marcel

Sau ba năm tôi vẫn quay lại đây. thật hữu ích :-)
Afr

15

Tôi biết rằng đó không phải là chính xác những gì bạn muốn, nhưng nếu bạn biết mã hóa ban đầu, có lẽ bạn có thể sử dụng convmvđể thay đổi mã hóa thành UTF-8, điều này sẽ khắc phục hầu hết các vấn đề.

Điều này làm việc cho tôi trên một thư mục với một số tên tệp Ba Lan được mã hóa không hợp lệ:

convmv -f cp1250 -t utf8 -r .

Lưu ý rằng lệnh này không thực sự đổi tên bất cứ thứ gì; thêm --notesttùy chọn để thực sự đổi tên các tập tin.


1
Đối với những người có một bộ tĩnh (hoặc không có hỗn hợp bộ ký tự đa dạng), convmvtùy chọn này rất đơn giản và hoàn hảo. Đối với OP, có vô số bộ ký tự tiềm năng, điều này có thể được hợp nhất với câu trả lời khác, vì convmvdường như biết khi nào hoặc khi nào nó không gặp phải định dạng chính xác. Bằng cách lặp qua các bộ ký tự, thông qua convmv --list, người ta sẽ mã hóa chúng đúng cách.

1
Điều này có nghĩa là, nếu, như OP, chạy một máy chủ Debian, chắc chắn người ta sẽ sử dụng UTF8 vào những ngày này, trong trường hợp đó, người ta có thể giữ các chữ cái gốc. Tôi đã có một thư mục gồm một số ký tự nordic và đã sử dụng: convmv -t utf8 --nfc -f iso-8859-1 --notest -r .- Việc --nfcnày phù hợp với Linux trước OS X hoặc lâu hơn, chỉ cần gõ convmvtừ bỏ các tùy chọn (hữu ích).

0

Tôi biết, bạn hỏi về việc đổi tên.

Nhưng bạn có thể tránh vấn đề khá dễ dàng bằng phần mềm như MusicBrainz Picard .

Nó có khả năng nhận dạng âm nhạc (vân tay âm thanh), tải xuống tất cả dữ liệu cần thiết (bao gồm cả ảnh bìa, nếu có) từ cơ sở dữ liệu MusicBrainz khổng lồ và di chuyển các tệp xung quanh để bộ sưu tập của bạn có thể phù hợp với bất kỳ mẫu nào bạn thích. Tôi đã sử dụng nó trong nhiều năm và nó luôn hoạt động hoàn hảo với mọi thứ từ Cyrilic đến Ả Rập; và tất nhiên (ít nhất là đối với các tập lệnh gốc Latinh) nó cũng có thể thực hiện chuyển đổi sang ASCII.

Với cách tiếp cận này, việc bộ sưu tập của bạn thực sự không quan trọng đến mức nào, miễn là các tập tin có thể đọc và hoàn thành.

(Tôi có đề cập đến nó miễn phí không? Cả trong bài phát biểu miễn phí và như bia miễn phí? Cả phần mềm và cơ sở dữ liệu ..?)

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.