Bagaimana cara mengganti nama file secara massal dengan penyandian yang tidak valid atau mengganti karakter yang disandikan secara massal?

13

Saya memiliki server debian dan saya hosting musik untuk stasiun radio internet. Saya mengalami masalah dengan nama dan jalur file karena banyak file mendapat penyandian yang tidak valid, misalnya:

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

Idealnya, saya ingin menghapus semua yang bukan surat A-Z / a-z atau angka 0-9 atau lari cepat - /menggarisbawahi _... Hasilnya akan terlihat seperti itu:

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

Bagaimana mencapai ini untuk banyak file dan direktori?

Saya telah melihat pertanyaan serupa ini: mengubah nama massal (atau menampilkan dengan benar) file dengan karakter khusus

Tapi ini hanya memperbaiki pengkodean, saya lebih suka pendekatan yang lebih ketat seperti dijelaskan di atas.

Afri
sumber

Jawaban:

13

Anda akan menjalankan beberapa masalah jika Anda ingin mengganti nama file dan direktori pada saat bersamaan. Mengganti nama file saja cukup mudah. Tetapi Anda ingin memastikan direktori juga diganti namanya. Anda tidak bisa begitu saja mv Motörhead/Encöding Motorhead/Encoding sejak Motorhead tidak akan ada pada saat panggilan berlangsung.

Jadi, kita perlu traversal mendalam-pertama dari semua file dan folder, dan kemudian ganti nama file atau folder saat ini saja. Berikut ini berfungsi dengan GNU find dan Bash 4.2.42 di OS X.

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

Anda dapat mengubah regex dengan menggunakan new="${f//[\\\/\:\*\?\"<>|]/}" jika Anda ingin mengganti apa pun yang tidak dapat ditangani Windows.

Simpan skrip ini sebagai rename.sh, buat itu dapat dieksekusi dengan chmod +x rename.sh. Lalu, sebut seperti itu rename.sh /some/path.

Pastikan untuk menyelesaikan tabrakan nama file apa pun (“ Notice "Pengumuman).

Jika kamu sangat yakin itu melakukan penggantian yang tepat, hapus echo dari skrip untuk benar-benar mengubah nama hal, bukan hanya mencetak apa yang dilakukannya.

Agar aman, saya akan merekomendasikan pengujian ini pada sebagian kecil file terlebih dahulu.


Opsi dijelaskan

Untuk menjelaskan apa yang terjadi di sini:

  • -depth akan memastikan direktori terulang lebih dulu, sehingga kami dapat "menggulung" semuanya dari awal. Biasanya, find melintasi secara berbeda (tetapi tidak lebih dulu).
  • -print0 memastikan find output adalah null-delimited, jadi kita bisa membacanya dengan read -d '' ke dalam file variabel. Melakukan hal itu membantu kita menangani semua jenis nama file aneh, termasuk yang memiliki spasi, dan bahkan baris baru.
  • Kami akan mendapatkan direktori file tersebut dirname. Jangan lupa untuk selalu mengutip variabel Anda dengan benar, jika tidak jalur apa pun dengan spasi atau karakter globbing akan mematahkan skrip ini.
  • Kami akan mendapatkan nama file (atau nama direktori) yang sebenarnya basename.
  • Lalu, kami menghapus karakter yang tidak valid dari $f menggunakan kemampuan penggantian string Bash. Invalid berarti segala sesuatu yang bukan huruf kecil atau besar, digit, garis miring ( \/ ), sebuah titik ( \. ), garis bawah, atau minus-tanda hubung.
  • Jika $f sudah bersih (nama yang dibersihkan identik dengan nama saat ini), lewati saja.
  • Jika $new sudah ada di direktori $d (mis., Anda memiliki file dengan nama resume dan résumé di direktori yang sama), keluarkan peringatan. Anda tidak ingin mengubah nama itu, karena, pada beberapa sistem, mv foo foo menyebabkan masalah. Jika tidak,
  • Kami akhirnya mengganti nama file asli (atau direktori) menjadi nama barunya

Karena ini hanya akan bertindak pada hierarki terdalam, penamaan ulang Motörhead/Encöding untuk Motorhead/Encoding dilakukan dalam dua langkah:

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

Ini memastikan semua penggantian dilakukan dalam urutan yang benar.


Contoh file dan uji coba

Mari kita asumsikan beberapa file dalam folder dasar bernama 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

Berikut ini adalah output dari menjalankan dalam mode debug (dengan echo di depan mv ), yaitu, perintah yang akan dipanggil, dan peringatan tabrakan:

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é

Perhatikan tidak adanya pesan untuk with-hyphen.txt, schedule, dan test diri.

slhck
sumber
1
Anda mungkin ingin menambahkan logika untuk menangani case tempat tujuan mv sudah ada, yang dapat terjadi (1) jika Anda memiliki file yang sudah bersih (menghasilkan mv foo foo ), atau (2) jika Anda memiliki file dengan nama yang sama kecuali untuk karakter khusus (mis., mv Encöding Encoding, di mana Anda sudah memiliki Encoding file di samping Encöding ).
Scott
Ide bagus, terima kasih. Adakah saran khusus tentang apa yang harus dilakukan dalam kasus itu? Memang - mencapai ini dengan cara yang bersih dan waras lebih sulit daripada yang terlihat pada awalnya. Jika Anda memiliki sesuatu, silakan mengedit saja.
slhck
Saya tidak percaya masuk akal untuk berpikir tentang menangani tabrakan secara otomatis - hanya mengidentifikasi mereka kepada pengguna dan biarkan dia menanganinya. Saya sudah mengedit jawaban Anda, seperti yang Anda sarankan.
Scott
+1 untuk menggunakan contoh dengan "Encöding" Terlalu banyak untuk! :-)
Marcel
Setelah tiga tahun saya masih kembali ke sini. sangat berguna! :-)
Afri
14

Saya tahu itu bukan apa yang Anda inginkan, tetapi jika Anda tahu penyandian aslinya, mungkin Anda bisa menggunakannya convmv untuk mengubah pengkodean ke UTF-8, yang seharusnya memperbaiki sebagian besar masalah.

Ini berfungsi untuk saya di folder dengan beberapa nama file Polandia yang disandikan tidak valid:

convmv -f cp1250 -t utf8 -r .

Perhatikan bahwa perintah ini sebenarnya tidak mengubah nama apa pun; menambahkan --notest opsi untuk benar-benar mengganti nama file.

mik01aj
sumber
1
Bagi mereka yang memiliki set statis (atau tidak memiliki campuran beragam rangkaian karakter), the convmv Opsi luar biasa sederhana dan sempurna. Untuk OP, yang memiliki banyak potensi karakter, ini bisa digabungkan dengan jawaban yang lain, karena convmv tampaknya tahu kapan atau kapan tidak menemukan format yang benar. Dengan mengulang melalui rangkaian karakter, via convmv --list, orang akan mendapatkan mereka dikodekan dengan benar.
1
Maksud saya, jika, sebagai OP, menjalankan server Debian, orang pasti akan menganggap UTF8 hari ini, dalam hal ini, seseorang dapat menyimpan huruf aslinya. Saya memiliki folder beberapa karakter nordic, dan menggunakan: convmv -t utf8 --nfc -f iso-8859-1 --notest -r . - --nfc adalah untuk menyesuaikan diri dengan Linux sebelum OS X atau lebih, cukup mengetik convmv menyerahkan opsi (berguna).
0

Saya tahu, Anda bertanya tentang penggantian nama.

Tetapi Anda dapat menghindari masalah dengan cukup mudah menggunakan perangkat lunak seperti MusicBrainz Picard .

Ia mampu mengidentifikasi musik (sidik jari audio), mengunduh semua data yang diperlukan (termasuk gambar sampul, jika tersedia) dari MusicBrainz database dan memindahkan file di sekitar sehingga koleksi Anda dapat sesuai dengan pola apa pun yang Anda suka. Saya menggunakannya selama bertahun-tahun dan selalu bekerja dengan baik dengan apa saja dari Cyrilic ke Arab; dan tentu saja (setidaknya untuk skrip berbasis Latin) juga dapat melakukan konversi ke ASCII.

Dengan pendekatan ini, tidak masalah seberapa berantakan / buruknya nama koleksi Anda, asalkan file-file tersebut dapat dibaca dan lengkap.

(Apakah saya menyebutkan itu gratis? Baik dalam kebebasan berbicara maupun dalam bir gratis? Baik perangkat lunak dan database ..?)

Alois Mahdal
sumber