Hindari mengganti spasi saat mengganti nama file

10

Saya mencoba mengubah nama file seperti ini:

for file in *;
do
mv -i "$file" "$(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g')";
done

Tetapi sedperintah mengganti semua spasi dengan _.

Bagaimana saya bisa mengedit sedperintah untuk membuatnya termasuk ruang bersama dengan karakter yang ditentukan? Saya sudah mencoba menggunakan \stetapi tidak berhasil ...

EDIT:
Misalnya: file trip: hill, harus diganti nama:, trip_ hilltetapi perintah di atas membuatnya trip__hill.

Zanna
sumber
Saya memindahkan beberapa file dari linux, ke Mac. Tetapi untuk beberapa alasan sistem Mac tidak dapat membaca semua nama file, jadi saya mencoba untuk mengganti nama file saya. Menambahkan spasi ke perintah di atas tidak berfungsi. Dan Anda benar: Saya ingin mengganti semua karakter dengan '_' kecuali yang ditentukan. Dan saya tidak tahu bagaimana cara memasukkan space char.
Harap perhatikan bahwa saya mencoba mengganti semua karakter dengan '_' kecuali yang ditentukan. Tidak ada pola khusus untuk file yang diganti namanya, jadi saya tidak dapat menggunakan perintah perl ini.

Jawaban:

11

Jangan parsing nama file dengan sed! Output dari echo "$file"mungkin tidak dapat diandalkan.

Gunakan rename. Pada 17.10 Anda harus menginstalnya terlebih dahulu

sudo apt install rename

Kemudian:

rename -n -- 's/[^-A-Za-z0-9_ .]/_/g' *

Catatan

  • hapus -nsetelah pengujian untuk benar-benar mengganti nama file
  • -- end-of-options jika file dimulai dengan -
  • [^-A-Za-z0-9_ .]karakter yang tidak ingin kami ganti - taruh -dulu atau terakhir sehingga tidak dapat menunjukkan rentang (itu diperlakukan secara harfiah di posisi ini).
  • Spasi dapat dimasukkan dalam kelas
  • . diperlakukan secara harfiah (dalam konteks regex lain itu adalah singkatan dari karakter apa pun dan perlu melarikan diri).

Ini juga berfungsi di sed:

$ echo 'trip: hill' | sed 's/[^-A-Za-z0-9 _.]/_/g'
trip_ hill

Jika saya menambahkan spasi di bagian akhir versi Anda, saya mendapatkan kesalahan:

$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._- ]/_/g'
sed: -e expression #1, char 22: Invalid range end

Tetapi dengan -pada akhirnya, itu bekerja:

$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._ -]/_/g'
trip_ hill

Jadi mungkin posisi tanda hubung menyebabkan masalah Anda ketika Anda menambahkan spasi. Tetapi saran untuk tidak mengurai nama file tetap berlaku!

Zanna
sumber
Perintah ini berfungsi terima kasih. Anda juga telah dengan jelas mengidentifikasi kesalahan dalam perintah yang saya gunakan.
2
Terima kasih lagi. Harap dicatat bahwa tidak perlu menggunakan garis miring '\' dalam hal menggunakan sed. Karena ini menambahkan '\' ke daftar karakter yang diabaikan.
2
@latach Itu adalah garis miring terbalik, tetapi Anda memang benar. Setelah menguji dan menggali sekitar saya menemukan yang .literal di kelas karakter. TIL!
Zanna
2

Anda juga dapat menggunakan shell, ekspansi parameter Bash dapat melakukan substitusi:

for f in ./* ; do
    mv "$f" "${f//[^-A-Za-z0-9._ ]/_}"
done

Double slash memberitahukannya untuk mengganti semua kecocokan, selain itu, sintaksinya mudah.

ilkkachu
sumber