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:
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
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.
mv
sudah ada, yang dapat terjadi (1) jika Anda memiliki file yang sudah bersih (menghasilkanmv 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 memilikiEncoding
file di sampingEncöding
).