Berbasis pola, nama file batch di terminal

48

Saya perlu mengganti nama berikut ini:

file_001_loremipsum.png
file_002_dolor.png
file_003_sit.png
file_004_amet.png
file_105_randomness.png

ke

upl_loremipsum.png
upl_dolor.png
upl_sit.png
upl_amet.png
upl_randomness.png

Bagaimana cara mewujudkannya hanya dengan satu baris perintah terminal?

Unamata Sanatarai
sumber
1
Versi python yang gagal berbasis regex yang bekerja secara rekursif pada semua subfolder: stackoverflow.com/a/39698169/191246
ccpizza

Jawaban:

79

Solusi untuk contoh di atas, menggunakan rename :

rename -v -n 's/file_\d{1,3}/upl/' file_*.png

Pemakaian:

rename [options] [Perl regex search/replace expression] [files]

Dari man rename:

   -v, --verbose
           Verbose: print names of files successfully renamed.
   -n, --no-act
           No Action: show what files would have been renamed.

ganti nama MUNGKIN ambil regex sebagai argumen.

Yang kami lihat adalah konten di antara tanda kutip tunggal '. Anda dapat menempatkan regex dipisahkan oleh /.

Formula: di s/(1)/(2)/mana (1)= pola pencarian, dan (2)= ganti pola.

Jadi, biasakan diri Anda dengan regex , dan nikmati penggantian nama file batch berdasarkan pola!

Unamata Sanatarai
sumber
14
Saya tahu ini Ubuntu, tetapi jika ada yang berakhir di sini meskipun mereka mencari solusi OS X (saya lakukan), renamemudah diinstal brew install rename.
sandstrom
Di Ubuntu 18.10, yang --no-actbendera --nonosebagai gantinya. Jawaban ini juga bisa sedikit lebih eksplisit: [files]merujuk pada pola pencocokan pola awal dalam direktori saat ini yang ingin diubah namanya secara potensial (misalnya, *cocok dengan semuanya, tetapi hanya di direktori saat ini).
Patrick Dark
Tautan Anda mengarah ke yang lain rename, yang memiliki format rename from to filedan tidak mendukung ekspresi reguler. Sebenarnya, distribusi Linux saya (Cent OS 7) memiliki versi yang persis seperti itu.
Alex Che
6

jika file berada dalam beberapa direktori, gunakan nama setelah menemukan seperti:

find -iname file_*.png -type f -exec rename -n 's/file_[0-9]{3}(.*\.png)/upl$1/' {} \;

-n setelah rename adalah untuk menguji, hapus untuk melanjutkan! -)

seperti ini, Anda mengasosiasikan menemukan dan mengganti nama kekuatan.

Secara pribadi, saya menggunakannya untuk mengganti nama sumber header .h ke .hpp

find -iname *.h -type f -exec rename 's/(.*\.)h/$1hpp/' {} \;
bcag2
sumber
Ada dokumentasi untuk -iname, -typedan -execbendera di manpages.ubuntu.com/manpages/bionic/man1/find.1.html#expression . ( find --helptidak terlalu membantu untuk perintah ini.) TL; DR: -inamecocok dengan pola huruf - tidak sensitif; -type fcocok dengan "file biasa"; dan -execmengeksekusi ekspresi sampai bertemu dengan ;karakter (titik koma).
Patrick Dark
5

Ini bisa dilakukan dengan sedikit keajaiban ekspansi parameter bash!

for f in file_[0-9]*_*; do mv $f upl_${f#file_[0-9]*_}; done

file_[0-9]*_*;- Pola pertama digunakan untuk melewati semua file yang dimulai dengan 'file_anynumber_'
${f#file_[0-9]*_}- Pola kedua file_[0-9]*_digunakan dalam ekspansi parameter yang memberitahu bash untuk menghapus 'file_anynumber_' dari mengemis string.

Untuk informasi lebih lanjut tentang Parameter expansion:

man bash
Basharat Sialvi
sumber
Perhatikan bahwa ini menggunakan gumpalan, bukan regex, sehingga [0-9]*akan cocok dengan satu digit diikuti oleh string apa pun. Mungkin ada cara yang lebih baik untuk mencocokkan angka saja, tetapi saya tidak bisa memikirkan sesuatu yang ringkas.
wjandrea
Apakah Anda juga dapat menyarankan cara agar perintah ini bekerja secara rekursif di semua subdirektori?
Francesco DM