Apa perintah yang baik untuk menghapus spasi, tanda hubung, dan garis bawah dari semua file dalam direktori, atau file yang dipilih?
Saya menggunakan perintah berikut dengan Thunar Custom Actions untuk membasmi nama file:
for file in %N; do mv "$file" "$(echo "$file" | tr -s ' ' | tr ' A-Z' '-a-z' | tr -s '-' | tr -c '[:alnum:][:cntrl:].' '-')"; done
Tapi perintah itu hanya menggantikan spasi dengan tanda hubung / tanda hubung dan huruf kecil yang dibatasi karakter.
Saya telah menggunakan perintah berikut di terminal untuk menghapus spasi dari ribuan nama file di folder, dan itu bekerja cukup cepat:
rename "s/ //g" *
Sekali lagi, ini hanya menghapus spasi, dan bukan tanda hubung / garis bawah dan menggarisbawahi juga.
Idealnya saya tidak ingin spasi, tanda hubung / tanda hubung, dan garis bawah pada nama file saya. Dan alangkah baiknya jika perintah itu bisa digunakan dengan Thunar Custom Actions pada file yang dipilih.
sumber
rename -i "s/[-_ ]//g" *
echo $file | sed -e 's/[ _-]//g'
; selesaiJawaban:
Versi
rename
yang disertakan denganperl
paket mendukung ekspresi reguler:Kalau tidak,
The
-i
bendera akan membuatrename
menggunakan modus interaktif, mendorong jika target sudah ada, bukannya Timpa diam-diam.Ganti nama Perl kadang-kadang disebut
prename
.Ganti nama Perl versus ganti nama util-linux
Pada sistem seperti-Debian, nama perl perl tampaknya menjadi default dan perintah di atas hanya akan berfungsi.
Pada beberapa distribusi,
rename
utilitas dari util-linux adalah default. Utilitas ini sepenuhnya tidak kompatibel dengan Perlrename
.Semua: Pertama, periksa untuk melihat apakah Perl
rename
tersedia di bawah namaprename
.Debian: Ganti nama Perl harus menjadi default. Ini juga tersedia sebagai
prename
. Therename
dieksekusi, meskipun, adalah di bawah kendali/etc/alternatives
dan dengan demikian bisa diubah untuk sesuatu yang berbeda.archlinux: Jalankan
pacman -S perl-rename
dan perintah tersedia sebagaiperl-rename
. Untuk nama yang lebih nyaman, buat alias. (Kiat topi: ChiseledAbs)Mac OSX Menurut jawaban ini ,
rename
dapat diinstal pada OSX menggunakan homebrew via:Unduh Langsung:
rename
juga tersedia dari Perl Monks:sumber
rename
yang Anda bicarakan. Yang dari util-linux -2.24.2-1.fc20.x86_64 tidak mendukung ekspresi reguler.rename
yang digunakan OP terlihat sepertiperl
versi dan bukanutil-linux
versi.rename
halaman manual untuk versi util-linux . Ngomong-ngomong, selain catatan itu, yang penting adalah OP mendapat jawabannya (dan Anda mendapat dukungan dari saya :-D).pacman -S perl-rename
saya kira Anda bisa alias.Saya akan mengganti semua
tr
perintah itu, dengansed
perintah substitusi, misalnya:sumber
Tidak menghitung
mv
, Anda tidak benar-benar membutuhkan proses luar untuk ini sama sekali - Anda dapat jenis hanya poof mereka.Meski begitu, itu berarti
mv
doa per file, dan jadi mungkinrename
lebih baik. Meskipun ini harus bekerja diberikan hanya POSIXmv
dalam$PATH
dan POSIX shell.Jadi, saya membuat semacam demo gila untuk ini. Set tes dihasilkan seperti:
Pertama-tama saya akan menjadi orang pertama yang mengakui bahwa perintah di atas menghasilkan hasil yang dapat lebih mudah diperoleh dengan cara lain. Tetapi cara lain kemungkinan tidak akan menunjukkan dengan baik apa yang mungkin dilakukan dengan
$IFS
sedikit imajinasi (sakit?) .Jadi bit pertama cukup mudah:
tee
mengeluarkan 5 salinan inputnya - heredocument dipanggilCGEN
dd
blok inputnya oleh baris baru pada 90 byte per blok dan pipa itu untuk ...sed
bergabung dengan 2 dari blok-blok itu pada dua\n
karakter ewline,'
kutip-tunggal hasil, dan menambahkan stringtouch --
untuk setiap siklus baris sebelum disalurkan ke ...sh
yang kemudian mengeksekusi semua input sebagai perintah shellThe
#CGEN
bit meskipun ... Nah, sebentar ...bagian bawah
printf
mencetak 252 0sberikutnya dari terakhir menerima 252
''
argumen null-string dan untuk setiap cetakan isi$n
diikuti oleh string" $i "
eval
menafsirkan argumen berikutnyaprintf
sebelum mencetak hasil penafsiran itu sebagai angka oktal yang ditopang oleh 2 backslash sepotongyang terakhir
printf
mencetak nilai-nilai byte untuk oktal-2 itu pada suatu waktu diikuti oleh string-_ ---___
untuk setiap pasangan$n
diinisialisasi ke persamaan yang akan bertambah$i
satu untuk setiap evaluasi kecuali bahwa ia melompati nilai 10, 39, atau 47 - (yang\n
ewline,'
kutip tunggal, dan/
garis miring dalam desimal ASCII secara berurutan )Hasil akhirnya adalah direktori yang berisi banyak nama file yang benar-benar jelek yang mengandung setiap byte di charset saya dari 1 hingga 255 kecuali tanda kutip tunggal (hanya dilewati untuk menghindari satu
sed s///
pernyataan lagi ) dan/
slash. Nama file tersebut terlihat seperti ini:Sekarang saya akan mendapatkan beberapa data pada file-file ini:
KELUARAN
Baik. Akhirnya, untuk bertindak:
KELUARAN
Keberhasilan! Anda dapat melihat sendiri:
sumber
IFS
+printf
set -- 'some arbitrary' args; eval printf '"%s\n"' "$(IFS=0; printf ' "$@" %s' $(printf %025d))"
new="$(IFS=" -_"; printf %s $1)"
bercabang subkulit (kecuali dalam ksh93) dan memiliki masalah dengan tailing baris baru. Pilihan lain adalah menggunakanIFS=' -_'; set -- $1; IFS=; new="$*"
(dan mengubah loop sementara Anda menjadi for for loop)[ -e x ]
akanx
menghasilkan false jika symlink ke file yang tidak ada atau tidak dapat diakses.jika Anda memiliki perl, Anda biasanya harus mengganti nama. Anda dapat melakukan:
dan tunjukkan bagaimana skrip ini ditulis:
Skrip ini tidak mendukung flag -i (ini adalah versi di sistem saya), tetapi mungkin skrip Anda mendukung. Bagaimana dengan argumen. Pertama adalah ekspresi reguler dengan format PCRE, berfungsi seperti filter, mengubah nama input menjadi nama output. Daftar nama input yang Anda berikan dengan tanda bintang '*'. misalnya, Anda melakukan:
'*' yang sebenarnya dapat diperluas ke:
Ketika Anda memiliki file jumlah sangat besar, Anda berada dalam perangkap. shell akan memperluas saluran Anda lebih lama dari yang diterima sistem. maka Anda dapat melakukan solusi menggunakan find atau xargs. menggunakan 'find' adalah masalah, karena mengganti nama akan dipanggil berkali-kali sama dengan jumlah file dalam direktori. lebih baik gunakan xargs dengan opsi -r. satu mengubah nama panggilan memodifikasi banyak file. sebagai contoh:
masalah terakhir, apa artinya:
ini adalah ekspresi reguler untuk memodifikasi nama. setelah pertama '/' adalah ruang. ini terdeteksi, dan diganti dengan string setelah '/' kedua. Tetapi ada string kosong yang diakhiri dengan '/' ketiga, maka ruang diganti dengan tidak ada. Opsi 'g' membuat ungkapan ini berulang. ekspresi akan berjalan untuk semua nama dari awal hingga akhir, dan mendeteksi semua ruang.
Tetapi bagaimana jika Anda memiliki karakter tab atau karakter 'putih' lainnya? ada pengganti untuk ini 's'. karakter apa yang tidak dibutuhkan lainnya? cukup tambahkan ke ekspresi. Semua dekat dengan tanda kurung, misalnya:
ini semua apakah kamu melihat kesamaan? Saya pikir Anda harus membaca man perlrequick dan man perlretut, ini menjelaskan kepada Anda (saya harap) bagaimana ekspresi reguler bekerja. Anda dapat menggunakan perintah rename dalam skrip Anda sendiri jika Anda membutuhkannya.
sumber
sh
Lingkaran shell berikut akan menghapus semua spasi, garis bawah, dan garis putus-putus dari nama-nama file di direktori saat ini, berhati-hati untuk tidak menimpa file yang ada:Untuk
bash
danksh
, dan sedikit lebih bertele-tele dengan logika:Hapus
echo
ketika Anda yakin itu melakukan apa yang Anda inginkan.The
tr
perintah akan menghapus (-d
) karakter apapun dalam himpunan karakter (' _-'
). Sangat penting untuk memiliki tanda hubung di awal atau akhir himpunan, atau itu akan ditafsirkan sebagai serangkaian karakter.sumber