GNU/Linux >> Belajar Linux >  >> Linux

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

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 memastikan find output dibatasi null, sehingga kita dapat membacanya dengan read -d '' ke dalam file 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 bernama resume dan ré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:

  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

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.


Linux
  1. Bagaimana Cara Mengganti Nama Banyak File Menggunakan Find?

  2. Bagaimana cara mengganti nama file dengan spasi menggunakan shell Linux?

  3. Bagaimana cara mengganti karakter dengan sed secara rekursif?

  1. Cara mengenkripsi file dengan gocryptfs di Linux

  2. Cara Mengonversi File ke Encoding UTF-8 di Linux

  3. Cara Unzip File di Linux (dengan Contoh)

  1. Cara Mengganti Nama File di Linux

  2. Bagaimana Mengganti Nama Kumpulan File Dengan Pola?

  3. Bagaimana cara menghapus karakter yang tidak valid dari nama file?