Bagaimana cara Batch Mengganti Nama File di Terminal macOS?

123

Saya memiliki folder dengan serangkaian file bernama:

prefix_1234_567.png
prefix_abcd_efg.png

Saya ingin menghapus satu garis bawah dan konten tengah secara berkelompok sehingga hasilnya adalah:

prefix_567.png
prefix_efg.png

Relevan tetapi tidak sepenuhnya menjelaskan:

kidnim
sumber
lihat range NSString dan NSMutableString dan metode substring
Grady Player
1
Sudahkah Anda mempertimbangkan solusi non-terminal untuk ini? Alur kerja Automator dapat melakukan jenis operasi ini dengan mudah. Anda dapat membuat alur kerja automator untuk mengganti nama semua file dan mengganti teks _*_dengan yang kosong.
Enkripsi
saya pikir automator tidak bisa melakukan wildcard
kidnim

Jawaban:

234

Dalam kasus khusus Anda, Anda dapat menggunakan bashperintah berikut ( bashadalah shell default di macOS):

for f in *.png; do echo mv "$f" "${f/_*_/_}"; done

Catatan: Jika ada kemungkinan nama file Anda dimulai dengan -, tempatkan -- sebelum mereka [1]:
mv -- "$f" "${f/_*_/_}"

Catatan: echoditambahkan sebelum melakukan uji mvcoba. Hapus itu untuk melakukan penggantian nama yang sebenarnya.

Anda dapat menjalankannya dari baris perintah atau menggunakannya dalam skrip.

  • "${f/_*_/_}"adalah aplikasi bash perluasan parameter : pola pencocokan substring (pertama) _*_diganti dengan literal _, secara efektif memotong token tengah dari namanya.
  • Perhatikan bahwa _*_ini adalah pola (ekspresi karakter pengganti, seperti yang juga digunakan untuk globbing), bukan ekspresi reguler (untuk mempelajari pola, menjalankan, man bashdan menelusuri Pattern Matching).

Jika Anda sering kali mengganti nama file secara batch, pertimbangkan untuk menginstal alat khusus seperti renameutilitas berbasis Perl . Di macOS Anda dapat menginstalnya menggunakan manajer paket populer Homebrew sebagai berikut:

brew install rename

Inilah persamaan dari perintah di atas menggunakan rename:

rename -n -e 's/_.*_/_/'  *.png

Sekali lagi, perintah ini melakukan uji coba; hapus -nuntuk melakukan penggantian nama sebenarnya.

  • Serupa dengan bashsolusi, s/.../.../melakukan substitusi teks, tetapi - tidak seperti in bash- ekspresi reguler digunakan.

[1] Tujuan dari argumen khusus --, yang didukung oleh sebagian besar utilitas, adalah untuk memberi sinyal bahwa argumen selanjutnya harus diperlakukan sebagai operan (nilai), bahkan jika mereka terlihat seperti opsi yang dimulai dengan -, seperti yang dicatat oleh Jacob C.

mklement0
sumber
3
jawaban yang bagus, bekerja dengan sempurna. Saya juga menghargai bahwa Anda telah kembali dan mengeditnya untuk menjelaskan lebih lanjut dan memberikan solusi yang lebih elegan jika saya mengulangi ini. sekali lagi, terima kasih banyak, sangat membantu
kidnim
4
Contoh menggunakan pengganti yang cocok ( .*-> $1), mis. Ubah nama Foo bar S01E01 biz baz.extmenjadi S01E01.ext:rename -n -e 's/.*(S[0-9]{2}E[0-9]{2}).*(\.[a-z]{2,4})/$1$2/' *
Steve Robbins
2
Suka ide penggunaan echountuk lari kering. Terima kasih atas tipnya!
James Wright
Sangat merekomendasikan hanya melakukanbrew install rename
Chris Redford
98

Untuk mengganti nama file, Anda dapat menggunakan renameutilitas:

brew install rename

Misalnya, untuk mengubah string pencarian di semua nama file di direktori saat ini:

rename -nvs searchword replaceword *

Hapus parameter 'n' untuk menerapkan perubahan.

Info lebih lanjut: man rename

David Thomas
sumber
1
OS Xversi GNU bash( x86_64-apple-darwin ) tidak menyertakan utilitas ganti nama.
l'L'l
4
Terima kasih, ya itu perlu dipasang melaluibrew install rename
David Thomas
2
Tip ini luar biasa! Saya mengetik rename -vs GLYCOPHORIN GLYCC *dan sekarang secara otomatis mengganti nama 450+ file. Dan juga super cepat.
Sander W. van der Laan
3
Luar biasa! Cintai bagian "tunjukkan apa yang akan diubah" SEBELUM itu benar-benar mengubah nama banyak hal!
Ben Duffin
3
Anda juga dapat menggunakan regex. ganti nama 's / 123 / onetwothree / g' *
Bryan
12

Anda bisa menggunakan sed:

ls * | sed -e 'p;s@_.*_@_@g' | xargs -n2 mv

hasil:

prefix_567.png prefix_efg.png

* untuk melakukan uji coba terlebih dahulu, ganti mvdi bagian akhir denganecho

Penjelasan:

  • e: opsional hanya untuk 1 perintah sed.
  • p: untuk mencetak input ke sed, dalam hal ini akan menjadi nama file asli sebelum penggantian nama
  • @: adalah pengganti dari / character agar sed lebih mudah dibaca. Artinya, daripada menggunakan sed s / search / replace / g, gunakan s @ search @ replace @ g
  • _. *: garis bawah adalah karakter escape untuk merujuk ke '.' karakter nol kali atau lebih (berbeda dengan karakter APA PUN di regex)
  • -n2: menunjukkan bahwa ada 2 keluaran yang perlu diteruskan ke mv sebagai parameter. untuk setiap masukan dari ls , perintah sed ini akan menghasilkan 2 keluaran, yang kemudian akan disuplai ke mv.
l'L'l
sumber
1
Solusi cerdas, jika agak misterius. Membuat ini lebih umum, sehingga juga mendukung nama file dengan spasi yang disematkan, menjadi lebih misterius: ls * | xargs -I % bash -c 'echo mv "%" "$(sed 's@_.*_@_@' <<<"%")"'(hapus echountuk benar-benar mengganti nama).
mklement0
2
Batin? Aku suka ini!
Bilal Akil
7

Saya memiliki sekumpulan file yang terlihat seperti ini: be90-01.png dan perlu mengubah tanda hubung menjadi garis bawah. Saya menggunakan ini, yang bekerja dengan baik:

for f in *; do mv "$f" "`echo $f | tr '-' '_'`"; done
JanB
sumber
2

Anda dapat menginstal renameperintah dengan menggunakan brew. lakukan brew install renamedan gunakan saja.

Nisim Joseph
sumber
1

Menggunakan mmv

mmv '*_*_*' '#1_#3' *.png
αғsнιη
sumber
Anda perlu menginstalnya terlebih dahulu sudo apt-get install mmv.
αғsнιη
1
Mengingat ini adalah OS X, prosedur penginstalan yang benar adalah brew install mmv.
buckaroo1177125
1

coba ini

for i in *.png ; do mv "$i" "${i/remove_me*.png/.png}" ; done

Berikut cara lain:

for file in Name*.png; do mv "$file" "01_$file"; done
Thiago
sumber