Kurangi 1 dari semua nama file (ganti namanya) di direktori.

17

Saya memiliki direktori yang berisi file gambar dengan nama suka

image1.jpg 
image2.jpg 
image3.jpg
...

Sayangnya, nama-nama gambar harus berbasis nol, jadi image1.jpgseharusnya image0.jpg, image2.jpgharus image1.jpgdan sebagainya.

Saya bisa menulis skrip untuk menghasilkan perintah mv seperti ini, memasukkannya ke dalam skrip shell, dan kemudian menjalankannya -

mv image1.jpg image0.jpg
mv image2.jpg image1.jpg
mv image3.jpg image2.jpg
...

Tapi saya kira ada cara yang lebih rapi untuk melakukannya di Unix. Jadi apa itu?

Wes
sumber
6
Itu sebenarnya cara paling sederhana untuk melakukannya, selama tidak ada celah. ( for i in $(seq 0 100); do mv image$[i+1].jpg image$i.jpg; done)
Ricky Beam
5
Apakah urutan gambar itu penting? Jika tidak, cukup ganti nama gambar terakhir dari imageN.jpgmenjadi image0.jpgdan Anda selesai.
jnovacho
@jnovacho, cukup pintar! Tapi ya, urutan gambar itu penting.
Wes

Jawaban:

20

Perl tua yang baik mengubah nama:

rename 's/(\d+)(\.jpg)/($1-1).$2/e' *

[Catatan]

Angka gambar harus lebih besar dari 0.

Dalam hal gambar lebih besar dari 9 dan belum memimpin 0s, gunakan $(ls -v1 *)untuk menghindari clobbering. Diusulkan oleh @arielf dan diperhatikan oleh @Graeme.

Jika ragu gunakan juga -vuntuk verbose dan -ntanpa tindakan.


sumber
Apa yang ditunjukkan "e"?
Wes
3
'e' berarti mengevaluasi, bagian pengganti akan dievaluasi. lihat jugaperlreref
6
File harus diteruskan dalam urutan menaik untuk menghindari clobber. Ini akan berfungsi dengan baik hanya jika ada kurang dari 10 file (atau jika angka memiliki nol di depan).
Graeme
Saya perhatikan ini sudah, juga tidak boleh ada 0dalam sumber.
2
ganti *di akhir dengan `ls -v1 *`dan Anda akan lebih aman dari musnah. Ini akan berubah dari angka terendah ke tertinggi.
arielf
6

Anda dapat menyalurkan mvperintah yang dihasilkan ke bash. Jadi Anda tidak perlu menyalinnya dalam skrip dan menjalankannya. Lihat:

command_that_generates_mv_commands | bash

Dan semuanya akan dieksekusi yang disalurkan ke bash.

kekacauan
sumber
Itu tidak rapi. :)Memecahkan masalah, jadi +1.
JMCF125
5

Anda dapat beralih pada keluaran ls, ini berfungsi untuk contoh Anda:

i=0 
for file in $(ls *.jpg | sort) ; do 
     mv $file $(echo $file | sed 's/[0-9]*.jpg$/'${i}'.jpg/')
     i=$((++i))
done

Anda harus berada di jalur yang sama dengan file Anda

babasbot
sumber
1
Lebih baik digunakan -iatau -ndengan mv, itu akan mencegah menimpa dalam kasus tepi.
Graeme
bukankah sort -Vlebih baik?
user80551
sorttidak akan berfungsi, itu akan ditampilkan image10.jpgsebelum image1.jpgyang mungkin menjadi masalah. Anda perlu sort -nk 1.8seperti pada jawaban @ Graeme.
terdon
@ user80551, sort -Vadalah ide bagus, akan menambahkannya ke jawaban saya. Mungkin ada kasus tepi lainnya, biasanya saran yang baik untuk menambahkan opsi semacam ini dengan pertanyaan seperti ini jika seseorang menyalin dan akhirnya melakukan beberapa kerusakan.
Graeme
4

Berikut ini tampaknya berfungsi untuk apa pun yang cocok dengan polanya imageNUMBER.jpg. Saya telah menempatkan echosebelum mvperintah untuk pertama-tama menunjukkan apa yang akan dilakukan perintah; untuk benar - benar melakukan penggantian nama, cukup hapusecho

for i in `ls image*.jpg|sort -V` ; do 
    x=`echo $i|sed -e "s/image\(.*\).jpg/\1/"`
    y=$(( $x - 1 ))
    echo mv -i $i image$y.jpg
done

Di baris pertama, ini ls image*.jpg|sort -Vakan menyebabkan file JPG didaftar dengan nomor naik dalam nama file. The x=garis ekstrak nomor dari nama file. The y=garis kemudian menurunkan angka per satu. Nama file input dan ynomor kemudian digunakan dalam mvperintah, di mana -ibendera akan memberi tahu Anda sebelum menimpa file.

Untuk pengujian kecil saya sendiri, ini menghasilkan output:

mv -i image1.jpg image0.jpg
mv -i image2.jpg image1.jpg
mv -i image123.jpg image122.jpg

Secara pribadi, saya sarankan mengganti nama menjadi nama file yang lebih berbeda, karena sekarang urutan pemrosesan file dapat membuat perbedaan besar.

brm
sumber
1
Lebih baik digunakan -iatau -ndengan mv, itu akan mencegah menimpa dalam kasus tepi.
Graeme
Saran yang sangat bagus, saya akan mengedit jawabannya
brm
Di macOS, Anda harus menggunakan sort -n, -Vopsi tidak ada.
Vincent Sit
4

Menggunakan perlskrip prename, yang dikaitkan untuk mengganti nama pada distro berbasis Debian, juga membutuhkan GNU find/ sort. File diletakkan dalam urutan menaik untuk mencegah penimpaan.

find . -regex '\./image[0-9]+\.jpg' -print0 | sort -zV |
  xargs -0 rename -n 's/(\d+)\.jpg$/@{[$1-1]}.jpg/'

Hapus -nsekali Anda yakin itu melakukan apa yang Anda inginkan. Akan memperingatkan tentang file yang sudah ada sebelum melakukannya. Namun selama itu menunjukkan file diubah namanya dalam urutan menaik, tidak akan ada konflik saat dijalankan secara nyata.

Graeme
sumber
File sudah ada masalah dengan yang ini.
Wes
4

Dengan zsh:

autoload zmv # (in ~/.zshrc)
zmv -Qf -n 'image(<->).jpg(n)' 'image$(($1-1)).jpg'

(hapus -nsaat senang).

(n)adalah untuk mengurutkan daftar secara numerik sehingga image9.jpgdiubah namanya sebelumnya image10.jpg.

Stéphane Chazelas
sumber