Ganti nama file secara massal

25

Saya memiliki sejumlah file:

10.3.100.179_01_20161018_230014_5335.jpg
10.3.100.179_01_20161018_231514_0814.jpg
10.3.100.179_01_20161018_233014_5706.jpg
10.3.100.179_01_20161018_234514_0896.jpg
10.3.100.179_01_20161018_230114_5395.jpg
10.3.100.179_01_20161018_231614_1145.jpg
10.3.100.179_01_20161018_233114_6047.jpg
10.3.100.179_01_20161018_234614_0547.jpg
10.3.100.179_01_20161018_230114_5492.jpg
10.3.100.179_01_20161018_231614_1264.jpg
10.3.100.179_01_20161018_233114_6146.jpg
10.3.100.179_01_20161018_234614_0658.jpg
10.3.100.179_01_20161018_230214_5630.jpg
10.3.100.179_01_20161018_231714_7135.jpg

Saya ingin mengganti nama dengan format ini:

10.4.100.135_01_20161013131108389_TIMING.jpg
10.4.100.135_01_20161013131111390_TIMING.jpg
10.4.100.135_01_20161013131114401_TIMING.jpg
10.4.100.135_01_20161013131117431_TIMING.jpg
10.4.100.135_01_20161013131120418_TIMING.jpg
10.4.100.135_01_20161013131123461_TIMING.jpg
10.4.100.135_01_20161013131126511_TIMING.jpg

Perlu menghapus _stempel waktu dan menambahkan _TIMING.

Jojo Mendoza
sumber
5
Silakan gunakan contoh yang konsisten dalam pertanyaan Anda. Sepertinya Anda ingin mengganti 10.3.100.179dengan 10.4.100.135. Apakah itu yang Anda inginkan atau Anda hanya ingin menghapus _TIMINGdan _dari waktu?
terdon
3
Waktu yang tepat untuk mengingatkan orang bahwa ada standar iso8601 untuk tanggal (yang berfungsi baik untuk nama file DAN untuk entri log) ^^ Jadi mungkin Anda harus mempertimbangkan kembali penggantian nama menjadi: YYYY-MM-DDThh: mm: ss.mmm (ex : file pertama Anda akan menjadi: 10.4.100.135_01_2016-10-13T13:11:08.389_TIMING.jpg(dan "WAKTU" bahkan bisa dihapus, karena sekarang terlihat jelas seperti tanggal dan jam (dan milidetik), terutama ketika standar menjadi lebih luas. T adalah bagian dari standar dan saya tumbuh untuk menyukainya (dan mengeluarkannya merusak standar ^^)
Olivier Dulac
@ OlivierDulac Saya tidak akan merekomendasikan menggunakan :nama file. Saya percaya Windows tidak mendukungnya.
Justin
@ Just point bagus. standar merekomendasikan menjatuhkannya untuk nama file. Saya memberikan versi dalam file
Olivier Dulac

Jawaban:

38

Instal renameutilsdan gunakan qmvdengan editor teks favorit Anda.

qmvmemuat semua nama di editor Anda dan ketika Anda menyimpan dan menutup itu berlaku perubahan Anda ke file yang sebenarnya. Jika perubahan tidak konsisten (mis. Dua file mendapatkan nama yang sama) itu akan dibatalkan tanpa menyentuh apa pun. Ini juga menangani nama melingkar dengan benar.

Saya biasanya melakukan:

$ qmv -f do

sehingga hanya menampilkan satu kolom nama (do: destination-only). Begini tampilannya:

qmw

Jika Anda menggabungkannya dengan banyak kursor dari SublimeText, Atom atau Visual Studio Code, itu membuat alat yang sangat bagus dan kuat untuk penggantian nama massal. Misalnya, untuk Atom, Anda akan melakukannya EDITOR="atom -w" qmv -f do.

ateijelo
sumber
1
Selamat datang di askUbuntu! Ini sangat keren!
αғsнιη
Tanda tangani hanya untuk +! saya t. ;)
J. Allan
2
Wow, alat yang bagus dan animasi GIF yang bagus. Jawaban pertama yang bagus, terima kasih! :)
Byte Commander
1
Terima kasih @KasiyA karena menyelipkan gambar dan berterima kasih kepada semua orang atas komentar positifnya.
ateijelo
1
@kasperd Ya, itu akan memperingatkan bahwa rename plan berisi kesalahan dan membuka konsol interaktif di mana tindakan lebih lanjut dapat diambil.
ateijelo
27

Gunakan rename...

rename -n 's/^([0-9]+\.[0-9]\.[0-9]+\.[0-9]+_[0-9]+_)([0-9]+)_([0-9]+)_([0-9]+)\.jpg/$1$2$3$4_TIMING\.jpg/' *

Dengan -nini akan menampilkan apa yang akan dilakukan tanpa melakukan perubahan:

rename(10.3.100.179_01_20161018_230014_5335.jpg, 10.3.100.179_01_201610182300145335_TIMING.jpg)
rename(10.3.100.179_01_20161018_231514_0814.jpg, 10.3.100.179_01_201610182315140814_TIMING.jpg)
rename(10.3.100.179_01_20161018_233014_5706.jpg, 10.3.100.179_01_201610182330145706_TIMING.jpg)
rename(10.3.100.179_01_20161018_234514_0896.jpg, 10.3.100.179_01_201610182345140896_TIMING.jpg)

Jika terlihat benar, hapus -n

$ rename 's/^([0-9]+\.[0-9]\.[0-9]+\.[0-9]+_[0-9]+_)([0-9]+)_([0-9]+)_([0-9]+)\.jpg/$1$2$3$4_TIMING\.jpg/' *
$ ls
10.3.100.179_01_201610182300145335_TIMING.jpg  10.3.100.179_01_201610182330145706_TIMING.jpg
10.3.100.179_01_201610182315140814_TIMING.jpg  10.3.100.179_01_201610182345140896_TIMING.jpg

Menjelaskan ...

  • s/something/something_else/ cari dan ganti
  • ^ bagian awal nama (anchoring)
  • [0-9] nomor berapa pun
  • + satu atau lebih dari karakter sebelumnya
  • \.literal .(tanpa \ini cocok dengan karakter apa pun)
  • () untuk menjaga bagian ini
  • $1$2$3$3 kembali referensi ke hal-hal yang cocok dan disimpan sebelumnya ()

Catatan: *di akhir perintah cocok dengan semua file yang terlihat di direktori saat ini. Gunakan glob yang lebih cocok jika perlu.

Zanna
sumber
2
Pada beberapa distro, perintah ini tersedia sebagai prename(p untuk perl, karena arg pertama adalah ekspresi perl)
Peter Cordes
12

mmv dapat melakukannya sebagai berikut:

mmv '*_*_*_*_*.jpg' '#1_#2_#3#4#5_TIMING.jpg'

10.3.100.179_01_20161018_230014_5335.jpg 10.3.100.179_01_201610182300145335_TIMING.jpg

# 1, # 2, # 3, ... merujuk masing-masing ke pencocokan '*' di sini.

Bahkan lebih pendek dengan:

mmv '*_*_*.jpg' '#1#2#3_TIMING.jpg'
αғsнιη
sumber
9

renamePendekatan lain :

$ rename -n 's/(.*)_(.*)_(.*)\./$1$2$3_TIMING./' *
10.3.100.179_01_20161018_230014_5335.jpg -> 10.3.100.179_01_201610182300145335_TIMING.jpg
10.3.100.179_01_20161018_230114_5395.jpg -> 10.3.100.179_01_201610182301145395_TIMING.jpg
10.3.100.179_01_20161018_230114_5492.jpg -> 10.3.100.179_01_201610182301145492_TIMING.jpg
10.3.100.179_01_20161018_230214_5630.jpg -> 10.3.100.179_01_201610182302145630_TIMING.jpg
10.3.100.179_01_20161018_231514_0814.jpg -> 10.3.100.179_01_201610182315140814_TIMING.jpg
10.3.100.179_01_20161018_231614_1145.jpg -> 10.3.100.179_01_201610182316141145_TIMING.jpg
10.3.100.179_01_20161018_231614_1264.jpg -> 10.3.100.179_01_201610182316141264_TIMING.jpg
10.3.100.179_01_20161018_231714_7135.jpg -> 10.3.100.179_01_201610182317147135_TIMING.jpg
10.3.100.179_01_20161018_233014_5706.jpg -> 10.3.100.179_01_201610182330145706_TIMING.jpg
10.3.100.179_01_20161018_233114_6047.jpg -> 10.3.100.179_01_201610182331146047_TIMING.jpg
10.3.100.179_01_20161018_233114_6146.jpg -> 10.3.100.179_01_201610182331146146_TIMING.jpg
10.3.100.179_01_20161018_234514_0896.jpg -> 10.3.100.179_01_201610182345140896_TIMING.jpg
10.3.100.179_01_20161018_234614_0547.jpg -> 10.3.100.179_01_201610182346140547_TIMING.jpg
10.3.100.179_01_20161018_234614_0658.jpg -> 10.3.100.179_01_201610182346140658_TIMING.jpg

Jika itu berfungsi seperti yang Anda inginkan, hapus -n.

terdon
sumber
5

Anda juga dapat menggunakan yang berikut ini. Pertama, buat cadangan file Anda dan coba ini:

find . -name "*.jpg" -type f -print0| while read -d $'\0' file
do
    #extension="${file##*.}"
    newfilename=$(echo "${file%.*}" | sed 's/\(.*\)_\(.*\)_/\1\2/')
    mv "$file" "$newfilename""_TIMING.jpg"
done

sed 's/\(.*\)_\(.*\)_/\1\2/')menghapus _karakter di cap waktu.

Sebagai contoh:

user@host$ ls -lart
total 8
drwxrwxr-x 6 user user 4096 Oct 21 10:21 ..
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230014_5335.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231514_0814.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_233014_5706.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_234514_0896.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230114_5395.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231614_1145.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_233114_6047.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_234614_0547.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230114_5492.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231614_1264.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_233114_6146.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_234614_0658.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230214_5630.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231714_7135.jpg
drwxrwxr-x 2 user user 4096 Oct 21 10:30 .

user@host$ find . -name "*.jpg" -type f -print0 | while read -d $'\0' file
> do
>  newfilename=$(echo "${file%.*}" | sed 's/\(.*\)_\(.*\)_/\1\2/')
>  mv $file $newfilename"_TIMING.jpg"
> done

10:35:20 t $ ls -lart
total 8
drwxrwxr-x 6 user user 4096 Oct 21 10:21 ..
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182300145335_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182315140814_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182330145706_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182345140896_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182301145395_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182316141145_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182331146047_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182346140547_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182301145492_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182316141264_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182331146146_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182346140658_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182302145630_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182317147135_TIMING.jpg
drwxrwxr-x 2 user user 4096 Oct 21 10:35 .
Mustafa DOGRU
sumber
1
ini solusi terbaik. Tentu saja, soultion Zanna sangat cocok untuk beberapa file, tetapi karena globbing dilakukan oleh shell, solusi mereka mungkin gagal pada sejumlah besar file (string perintah terlalu lama).
rexkogitans
@rexkogitans: Jika Anda menggunakan sistem Linux modern (yaitu versi Ubuntu mana pun), batas panjang baris perintah adalah beberapa megabita. Dan jika ini merupakan masalah, Anda dapat menggunakan find -maxdepth 1 -exec rename ... {} +untuk batch daftar direktori saat ini ke baris perintah rename. (tambahkan -name *.jpgatau apa pun yang Anda inginkan). Itu akan mengeksekusi lebih cepat daripada loop shell yang fork + execs seddan mvuntuk setiap nama file, bukan hanya mengubah nama system call. (Anda bisa menyingkirkan sedmenggunakan barang-barang regex built-in bash, tetapi forking mvmasih lambat-ish.)
Peter Cordes
2

Anda mungkin selesai, tetapi inilah solusi (sederhana) semua bash:
Apakah "sederhana ... solusi bash" sebuah oxymoron?

#!/bin/bash

#loop through all files ending in .jpg
for f in *.jpg;
do

    #cut out everything to the timestamp
    firsthalf=${f%_*_*_*}

    #get from the timestamp on
    lasthalf=${f#*_*_}

    #remove (all) underscores from timestamp
    #note the 2 forward slashes...
    lasthalf=${lasthalf//_/}

    #get our extension
    ext=${lasthalf##*.}

    #now we can remove the extension
    lasthalf=${lasthalf%.*}

    #rename the file
    #change `mv` to `echo` if you want to do a trial run first...
    mv "$f" "${firsthalf}_${lasthalf}_TIMING.${ext}"

done;

PS: Logika dalam loop diuji dengan salah satu nama file contoh Anda. Itu berlalu.

J. Allan
sumber
1
Mungkin lebih baik menggunakan bash regex dengan [[ $f ~= (.*)_(.*)_(.*)_(.*)\.jpg ]]; newname=${BASH_REMATCH[1]${BASH_REMATCH:2:4}TIMING.jpgatau sesuatu. (benar-benar belum teruji dan mungkin salah, tetapi ide umumnya adalah grup tangkap masuk ke array BASH_REMATCH.)
Peter Cordes
@PeterCordes: Itu poin bagus! Saya tidak pernah menggunakan ( bash) menangkap grup, dan sejujurnya, bash bukan bahasa pertama yang saya coba. (Saya pikir bashitu bahasa yang jelek.) Namun, itu adalah solusi yang baik dan itu mengajarkan saya sesuatu yang sangat pujian.
J. Allan
Yup, alasan utama untuk melakukan banyak pemrosesan teks dalam bash murni adalah ketika menulis fungsi penyelesaian-tab yang seharusnya cepat. Ini membawa arti yang sama sekali baru ke frasa "kode jelek" ...
Peter Cordes
@PeterCordes: Saya mengerti maksud Anda, meskipun saya tidak berpikir bahwa kode itu "jelek." Ini mungkin bukan solusi 2 baris yang Anda berikan, tetapi tidak sulit untuk membaca sejauh yang saya ketahui; ditambah lagi komentarnya bagus ...
J. Allan
Saya berbicara tentang kode bash-completion secara umum menjadi jelek (atau setidaknya sulit dibaca). Ini sebenarnya tidak benar-benar jelek, hanya agak membengkokkan pikiran (misalnya melewati argumen oleh ref di bash dilakukan dengan meneruskan nama variabel dan memiliki callee digunakan printf -v "$3" ...untuk mengatur variabel yang namanya ada $3.) Membongkar seluruh baris perintah dan meletakkannya kembali bersama-sama cukup sulit untuk mengikuti / debug, setidaknya saya menemukannya seperti itu ketika mencoba untuk membersihkannya / memperbaiki bug. Lihat kode pada github
Peter Cordes
1

Jika Anda bisa menggunakan GUI, saya akan merekomendasikan pyRenamer .

Ada di sebagian besar distribusi, fi di Ubuntu:

sudo apt-get install pyrenamer

Itu dapat melakukan semua yang Anda inginkan dan banyak lagi.

  • Itu dapat menggunakan pola, menambah atau menekan teks.
  • Itu dapat mengakses data EXIF ​​jika mengganti nama foto, sehingga Anda dapat menghasilkan pola berdasarkan tanggal / waktu, dll ...
  • Dapat menggunakan beberapa metadata jika mengganti nama file musik.
  • Selain itu, ia memiliki pratinjau , yang dapat mencegah beberapa kesalahan sulit untuk dikembalikan.
jrierab
sumber
Kepada para downvoter ... Ingin menjelaskan mengapa? OP tidak menentukan apakah GUI adalah opsi atau tidak. Saya melihat sebagian besar jawaban masuk ke konsol / cara skrip, tetapi banyak pengguna akan menghargai solusi GUI. Atau mungkin pyRenamer memiliki beberapa kekurangan yang tidak saya sadari. Bagaimanapun, saya ingin tahu alasan untuk downvotes.
jrierab
Mungkin saya juga menyarankan Thunar Bulk Renamer untuk pendekatan GUI interaktif tajam.
Tony Martin
@TonyMartin Ini harus menjadi komentar di bawah pertanyaan, ini tidak ada hubungannya dengan jawaban
Sergiy Kolodyazhnyy
0

Berikut mentah Anda built-in find + xargs+ sed+ mv(oneliners cinta) oneliner:

find . -name "*.jpg" -print0 | sort -z | xargs -0 sh -c 'for filename; do mv "$filename" $(echo "${filename}" | sed "s/\([0-9]\{8\}\)_\([0-9]\{6\}\)_\([0-9]\{4\}\)/\1\2\3_TIMING/g"); done' sh

Penjelasan:

  • find . -name "*.jpg" | sort | xargs sh -c <command> sh : daftarkan semua JPEG di direktori saat ini kemudian jalankan perintah shell untuk masing-masing (pengurutan adalah opsional tentu saja, tetapi pertahankan sedikit lebih bersih jika Anda masuk ke suatu tempat)

  • -print0, -z, -0: Itu adalah kebiasaan yang baik untuk item terpisah dengan biner 0ketika tokenizing nama file untuk menghindari masalah dengan in-the-middle putih-ruang (tidak kasus Anda meskipun)

  • mv "$filename" $(echo "${filename}" | sed "s/\([0-9]\{8\}\)_\([0-9]\{6\}\)_\([0-9]\{4\}\)/\1\2\3_TIMING/g");: (Backslashes di sed's regex tidak membantu mudah dibaca, tetapi adalah sederhana) mengubah nama setiap file dengan mengganti urutan garis bawah-separeted dari 8 + 6 + 4 digit dengan Rangkaian berdekatan ditambah ini _TIMINGhal ( \iyang backreference ke i- grup regex).


Ref: Xargs - man sed

Campa
sumber