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?


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.


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.


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


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.


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.


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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.