cara mengganti nama beberapa file dengan mengganti string pada nama file? string ini mengandung "#"

43

https://serverfault.com/questions/70939/how-to-replace-a-text-string-in-multiple-files-in-linux

https://serverfault.com/questions/228733/how-to-rename-multiple-files-by-replacing-word-in-file-name

https://serverfault.com/questions/212153/replace-string-in-files-with-certain-file-extension

https://serverfault.com/questions/33158/searching-a-number-of-files-for-a-string-in-linux

Artikel-artikel yang disebutkan di atas semuanya menjawab pertanyaan saya. Namun tidak satupun dari mereka yang bekerja untuk saya. Saya menduga itu karena string yang saya coba ganti memiliki # di dalamnya. Apakah ada cara khusus untuk mengatasi ini?

Saya memiliki file gambar yang é diganti dengan # U00a9 selama migrasi situs. Ini terlihat seperti ini:

Lucky-#U00a9NBC-80x60.jpg
Lucky-#U00a9NBC-125x125.jpg
Lucky-#U00a9NBC-150x150.jpg
Lucky-#U00a9NBC-250x250.jpg
Lucky-#U00a9NBC-282x232.jpg
Lucky-#U00a9NBC-300x150.jpg
Lucky-#U00a9NBC-300x200.jpg
Lucky-#U00a9NBC-300x250.jpg
Lucky-#U00a9NBC-360x240.jpg
Lucky-#U00a9NBC-400x250.jpg
Lucky-#U00a9NBC-430x270.jpg
Lucky-#U00a9NBC-480x240.jpg
Lucky-#U00a9NBC-600x240.jpg
Lucky-#U00a9NBC-600x250.jpg
Lucky-#U00a9NBC.jpg

dan saya ingin mengubahnya menjadi seperti ini:

Lucky-safeNBC-80x60.jpg
Lucky-safeNBC-125x125.jpg
Lucky-safeNBC-150x150.jpg
Lucky-safeNBC-250x250.jpg
Lucky-safeNBC-282x232.jpg
Lucky-safeNBC-300x150.jpg
Lucky-safeNBC-300x200.jpg
Lucky-safeNBC-300x250.jpg
Lucky-safeNBC-360x240.jpg
Lucky-safeNBC-400x250.jpg
Lucky-safeNBC-430x270.jpg
Lucky-safeNBC-480x240.jpg
Lucky-safeNBC-600x240.jpg
Lucky-safeNBC-600x250.jpg
Lucky-safeNBC.jpg

MEMPERBARUI:

Semua contoh ini dimulai dengan "LU00a9ucky tetapi di sini ada banyak gambar dengan nama yang berbeda. Saya hanya menargetkan bagian" # U00a9 "dari string yang akan diganti dengan" safe ".

Komunitas
sumber
3
Jadi apa yang sudah Anda coba? Saya melihat bahwa Anda telah menautkan ke beberapa pertanyaan dan mengatakan mereka gagal, tetapi bagaimana mereka gagal? IMO contoh terbaik menggunakan renameperintah. Saya menduga nama Anda akan sesederhana rename -n 's/#/safeNBC/' *.jpg.
Zoredache
Saya mencoba rename -n 's/#U00a9/safe/' *.jpgdan perintah itu diterima tetapi tidak ada perubahan terjadi.
Tentu, seperti yang akan Anda lihat dari dokumentasi yang Anda tinjau, itu -nadalah no actpilihannya. Yang memungkinkan Anda melihat apakah itu berfungsi sebelum Anda benar-benar menggunakannya. Apakah output di layar menunjukkan potensi nama baru dengan benar?
Zoredache
Saya minta maaf saya menyalin dan menempelkan contoh Anda tanpa menaruh perhatian penuh, saya melakukan perintah ganti nama tanpa -n. Saya percaya @DTK mengatasi masalah ini, saya tidak lolos dari #.
Mengganti string dalam nama file di MacOS: superuser.com/questions/152627/…
Anton Tarasenko

Jawaban:

65

Untuk mengganti #dengan somethingelseuntuk nama file di direktori saat ini (tidak rekursif) Anda dapat menggunakan utilitas ganti nama GNU :

rename  's/#/somethingelse/' *

Karakter seperti -harus lolos dengan a \.

Untuk kasus Anda, Anda ingin menggunakannya

rename 's/#U00a9/safe/g' *

Perhatikan bahwa jika Anda hanya ingin mengoperasikan pada pilihan file tertentu, misalnya saja *.jpg, sesuaikan input akhir agar sesuai dengan pilihan itu:

rename 's/#U00a9/safe/g' *.jpg

Untuk melakukan tes sebelum benar-benar mengubah nama file, gunakan -nbendera:

demo/> ls                               
Lucky-#U00a9NBC-125x125.jpg  
Lucky-#U00a9NBC-150x150.jpg 

demo/> rename -n 's/#U00a9/safe/g' *.jpg
rename(Lucky-#U00a9NBC-125x125.jpg, Lucky-safeNBC-125x125.jpg)
rename(Lucky-#U00a9NBC-150x150.jpg, Lucky-safeNBC-150x150.jpg)

Untuk OS X, GNU rename dapat diinstal dengan menggunakan homebrew : brew install rename.

KrisWebDev
sumber
Ini tidak berfungsi pada mesin saya (Arch Linux), tetapi jawaban mik berhasil.
marcvangend
@marcvangend Versi apa renameyang Anda gunakan? # sudo pacman -S perl-renameakan menginstal versi perl, yang lebih kuat dan mungkin cukup untuk membuat jawaban ini berfungsi untuk Anda.
John Gowers
@ JohnGowers Terima kasih! Saya tidak menyadari ada dua versi. Di sistem saya, rename --versionkembali rename from util-linux 2.29.2jadi itu memang bukan versi perl.
marcvangend
5
Ada dua renameutilitas umum tetapi tidak ada yang dikembangkan oleh GNU: Distribusi berbasis Debian menyertakan renameutilitas dengan paket Perl mereka sementara distribusi berbasis Red Hat menggunakan renameutilitas dari util-linuxdari dari Linux Kernel Organization. Tautan Anda ke fungsirename C dari perpustakaan standar GNU.
Anthony G - keadilan untuk Monica
2
Dalam jawaban ini, mengapa kita harus menulis /gdirename 's/#U00a9/safe/g' *
Nikhil
24

temukan daftar file lalu ganti kata kunci. di bawah ini adalah contohnya

find . -name '*jpg' -exec bash -c ' mv $0 ${0/\#U00a9NBC/safeNBC}' {} \;
Sujit Dhamale
sumber
1
Anda memerlukan tanda kutip ganda di sekitar mvargumen Anda , jika ada spasi dalam namanya
Stop Harming Monica
Saya perlu mengganti semua file * _spec.rb ke * _controller_spec.rb dan solusi Anda berhasil untuk saya. Terima kasih.
jedi
Terima kasih. Ini menyelesaikan masalah saya
Fabio Souza
19

Ini tidak sulit, cukup pastikan untuk lolos dari octothorpe (#) dalam nama dengan mendahulukan slash terbalik (\).

find . -type f -name 'Lucky-*' | while read FILE ; do
    newfile="$(echo ${FILE} |sed -e 's/\\#U00a9/safe/')" ;
    mv "${FILE}" "${newfile}" ;
done 
Komunitas
sumber
Penjelasan Anda masuk akal, keluar dari #suara seperti yang saya butuhkan. Saya tidak melihat garis miring terbalik dalam contoh Anda. Seharusnya terlihat seperti ini: s/\#U00a9/safe/
@LeonFrancisShelhamer tangkapan yang bagus. Itu menelan backslash. Saya akan memodifikasi.
17

Untuk keluar #dari shell, cukup gunakan tanda kutip tunggal ( '#'), tanda kutip ganda ( "#"), atau garis miring terbalik ( \#).

Yang paling sederhana dalam kasus Anda adalah menggunakan renameperintah (jika tersedia):

rename '#U00a9' safe *.jpg
mik
sumber
2
Terima kasih. Sementara jawaban tertinggi terpilih ( rename 's/#/somethingelse/' *) tidak berfungsi pada mesin saya (Arch Linux), yang ini berhasil.
marcvangend
1
Ini berfungsi menggunakan perintah rename dari util-linux.
imclean
10

tidak yakin bagaimana cara sed, tetapi Anda dapat mencoba ini dalam bash shell:

for f in Lucky-#U00a9NBC-*.jpg; do mv -v "$f" "${f/#U00a9/safe}"; done;

penjelasan:

  1. loop melalui semua nama file yang cocok dengan glob (Lucky- # U00a9NBC - *. jpg)
  2. mengganti nama file menggunakan perintah pindah (mv)
  3. menggunakan substitusi parameter bash asli $ {var / Pattern / Replacement} untuk membuat nama baru ("$ {f / # U00a9 / safe}")

Lebih lanjut tentang substitusi parameter (yang IMO sangat kurang): http://www.tldp.org/LDP/abs/html/parameter-substitution.html

Gregory Patmore
sumber
Walaupun kode ini dapat menjawab pertanyaan, itu tidak terlalu berguna dengan sendirinya. Menjelaskan bagaimana cara memecahkan masalah akan meningkatkan kegunaan dan nilai jangka panjang dari jawabannya.
Anthony G - keadilan untuk Monica
menambahkan penjelasan langkah-langkah dan bacaan lebih lanjut sesuai komentar Anthony.
Gregory Patmore
1

Contoh di atas tidak berfungsi pada sistem saya (CentOS 5.6) jadi saya menemukan perintah (mungkin lebih spesifik sistem) yang berfungsi (catatan: perlu melarikan diri '#' dengan \di baris perintah):

rename \#U00a9 safe *.jpg

[Juga: Saya belum memiliki reputasi yang cukup untuk berkomentar, jadi dalam menanggapi pertanyaan Nikhil mengenai penggunaan /gdalam rename 's/old_string/new_string/g'(diajukan dalam komentar untuk jawaban lain di atas):

Gunakan gpengubah untuk melakukan substitusi 'global' (yaitu, untuk mengganti new_string dengan old_string sebanyak yang terjadi old_string). Ini seharusnya tidak perlu dalam jawaban saya karena renameakan diterapkan ke semua file yang ditentukan dengan *. Lihat https://www.computerhope.com/unix/rename.htm untuk penjelasan singkat tentang ini dan pengubah lainnya.]

Ezra Citron
sumber
Benar; OS turunan Fedora seperti CentOS memiliki versi berbeda dari renameOS turunan Debian. Lihat unix.stackexchange.com/a/238862/135943 . Omong-omong, CentOS 5.6 sudah cukup tua dan saya sarankan Anda memperbarui.
Wildcard
Ah, terima kasih atas penjelasan + tautannya. OS yang ketinggalan jaman sedang bekerja dan jadi tidak tergantung pada saya untuk melakukan upgrade :) tetapi sebuah cluster baru sedang dibangun dan mungkin kita akan melakukan upgrade ketika kita pindah ...
Ezra Citron
0

Inilah solusi DTK yang dibungkus dengan fungsi bash yang dapat digunakan kembali:

function renameFilesRecursively () {

  SEARCH_PATH="$1"
  SEARCH="$2"
  REPLACE="$3"

  find ${SEARCH_PATH} -type f -name "*${SEARCH}*" | while read FILENAME ; do
      NEW_FILENAME="$(echo ${FILENAME} | sed -e "s/${SEARCH}/${REPLACE}/g")";
      mv "${FILENAME}" "${NEW_FILENAME}";
  done

}

Inilah cara Anda dapat menggunakannya:

renameFilesRecursively /home/user/my-files apple orange
Slava Fomin II
sumber
0

Sebenarnya renamememiliki opsi tepat untuk yang dipanggil --substatau -ssingkatnya. Tidak perlu menggunakan sintaks regex.

rename -s '#U00a9' 'safe' *

Jika Anda ingin mengganti / mengganti banyak kejadian, gunakan --subst-allatau -S.

BTW, saya hanya ingin mengganti string dengan tidak ada (menghapusnya dari nama file) ... baik kami juga memiliki opsi untuk itu -d/--deletedan -D/--delete-all:

rename -d '#U00a9' *
Lapin
sumber
-1

Pilihan lain adalah menggunakan pyRenamer, aplikasi yang dibuat khusus untuk penggantian nama batch.

Dapat diinstal dengan sudo apt-get install pyrenamer

Untuk detail penggunaan, lihat file README-nya di GitHub .

Sajna T
sumber
1
Jika Anda benar-benar berpikir ini dapat menjawab pertanyaan, harap tambahkan beberapa penjelasan untuk jawaban Anda. Dengan sendirinya, itu hanya menginstal paket. Anda harus menjelaskan apa yang dilakukan perintah dan memberikan contoh yang menangani persyaratan spesifik OP.
roaima