Saya tahu itu bukan yang Anda inginkan, tetapi jika Anda tahu penyandian aslinya, mungkin Anda dapat menggunakan convmv
untuk mengubah penyandian ke UTF-8, yang akan memperbaiki sebagian besar masalah.
Ini bekerja untuk saya pada folder dengan beberapa nama file Polandia yang disandikan tidak valid:
convmv -f cp1250 -t utf8 -r .
Perhatikan bahwa perintah ini sebenarnya tidak mengganti nama apa pun; tambahkan --notest
opsi untuk benar-benar mengganti nama file.
Anda akan mengalami beberapa masalah jika ingin mengganti nama file dan direktori pada saat yang sama. 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 memerlukan traversal mendalam terlebih dahulu dari semua file dan folder, lalu ganti nama file atau folder saat ini saja. Berikut ini bekerja dengan GNU find
dan Bash 4.2.42 di OS X saya.
#!/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 oleh Windows.
Simpan skrip ini sebagai rename.sh
, membuatnya dapat dieksekusi dengan chmod +x rename.sh
. Lalu, sebut saja seperti rename.sh /some/path
.
Pastikan untuk menyelesaikan konflik nama file apa pun (“Notice
” pengumuman).
Jika Anda sangat yakin itu melakukan penggantian yang tepat, hapus echo
dari skrip untuk benar-benar mengganti nama sesuatu alih-alih 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 diulang mendalam-pertama, sehingga kita dapat "menggulung" semuanya dari akhir. Biasanya,find
melintasi secara berbeda (namun bukan luasnya terlebih dahulu).-print0
memastikanfind
output dibatasi null, sehingga kita dapat membacanya denganread -d ''
ke dalamfile
variabel. Melakukan hal itu membantu kami menangani semua jenis nama file yang aneh, termasuk yang memiliki spasi, dan bahkan baris baru.- Kita akan mendapatkan direktori file dengan
dirname
. Jangan lupa untuk selalu mengutip variabel Anda dengan benar, jika tidak jalur apa pun dengan spasi atau karakter globbing akan merusak skrip ini. - Kita akan mendapatkan nama file sebenarnya (atau nama direktori) dengan
basename
. - Kemudian, kami menghapus karakter yang tidak valid dari
$f
menggunakan kemampuan penggantian string Bash. Tidak valid berarti apa pun yang bukan huruf kecil atau besar, angka, garis miring (\/
), titik (\.
), garis bawah, atau tanda hubung minus. - Jika
$f
sudah bersih (nama yang dibersihkan identik dengan nama saat ini), lewati saja. - Jika
$new
sudah ada di direktori$d
(misalnya, Anda memiliki file bernamaresume
danrésumé
di direktori yang sama), keluarkan peringatan. Anda tidak ingin mengganti namanya, karena, pada beberapa sistem,mv foo foo
menyebabkan masalah. Jika tidak, - Kami akhirnya mengganti nama file asli (atau direktori) dengan nama barunya
Karena ini hanya akan bekerja pada hierarki terdalam, mengganti nama Motörhead/Encöding
ke Motorhead/Encoding
dilakukan dalam dua langkah:
mv Motörhead/Encöding Motörhead/Encoding
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
Ini adalah output dari proses 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
itu sendiri.