Saya perlu mengganti nama kira-kira. 70.000 file. Misalnya: Dari sb_606_HBO_DPM_0089000
ke sb_606_dpm_0089000
dll.
Kisaran nomor berubah dari 0089000
menjadi 0163022
. Itu hanya bagian pertama dari nama yang perlu diubah. semua file berada dalam satu direktori, dan diberi nomor urut (urutan gambar). Angka-angka harus tetap tidak berubah.
Ketika saya mencoba ini di bash grizzles pada saya bahwa 'Daftar argumen terlalu panjang'.
Edit:
Saya pertama kali mencoba mengubah nama satu file dengan mv
:
mv sb_606_HBO_DPM_0089000.dpx sb_606_dpm_0089000.dpx
Kemudian saya mencoba mengubah nama suatu range (saya belajar di sini minggu lalu bagaimana memindahkan banyak file, jadi saya pikir sintaks yang sama mungkin bekerja untuk mengubah nama file ...). Saya pikir saya sudah mencoba yang berikut (atau yang sejenisnya):
mv sb_606_HBO_DPM_0{089000..163023}.dpx sb_606_dpm_0{089000..163023}.dpx
ARG_MAX
. Karena pertanyaan ini secara eksplisit meminta solusi baris perintah, solusi GUI (mungkin sama) seperti pada pertanyaan lain juga tidak cocok.mv {1..2} {3..4}
tidak bekerja, yang merupakan masalah yang sama sekali berbeda dariARG_MAX
... Semua orang yang menjawab mungkin akan merasakan hal yang sama! Jadi, dari sudut pandang saya, saya berharap Anda akan mengembalikan suntingan terakhir Anda dan, jika Anda mau, tanyakan pertanyaan baru tentangmv
ing dengan rentangargument list too long
kesalahan. Tidak perlu mengklarifikasi lebih lanjut, ini jelas bukan penipuan karena kami membutuhkan solusi untuk berurusan dengan ARG_MAX dan jawaban dalam duplikat yang diusulkan tidak melakukan itu.Jawaban:
Salah satu cara adalah dengan menggunakan
find
dengan-exec
, dan+
pilihan. Ini membangun daftar argumen, tetapi memecah daftar menjadi panggilan sebanyak yang diperlukan untuk beroperasi pada semua file tanpa melebihi daftar argumen maksimum. Sangat cocok ketika semua argumen akan diperlakukan sama. Inilah yang terjadi denganrename
, meskipun tidak denganmv
.Anda mungkin perlu menginstal nama Perl:
Maka Anda dapat menggunakan, misalnya:
Hapus
-n
setelah pengujian, untuk benar-benar mengganti nama file.sumber
Saya akan menyarankan tiga alternatif. Masing-masing adalah perintah baris tunggal yang sederhana, tetapi saya akan memberikan varian untuk kasus yang lebih rumit, terutama jika file yang akan diproses dicampur dengan file lain dalam direktori yang sama.
mmv
Saya akan menggunakan perintah mmv dari paket dengan nama yang sama :
Perhatikan bahwa argumen dilewatkan sebagai string, sehingga ekspansi glob tidak terjadi di shell. Perintah menerima tepat dua argumen, dan kemudian menemukan file yang sesuai secara internal, tanpa batasan ketat pada jumlah file. Perhatikan juga bahwa perintah di atas mengasumsikan bahwa semua file yang cocok dengan gumpalan pertama harus diganti namanya. Tentu saja Anda bebas untuk lebih spesifik:
Jika Anda memiliki file di luar rentang angka yang diminta dalam direktori yang sama, Anda mungkin lebih baik dengan perulangan nomor yang diberikan lebih lanjut dalam jawaban ini. Namun Anda juga bisa menggunakan urutan doa mmv dengan pola yang sesuai:
putaran angka
Jika Anda ingin menghindari memasang apa pun, atau perlu memilih dengan rentang nomor menghindari kecocokan di luar kisaran ini, dan Anda siap untuk menunggu 74.023 permintaan perintah, Anda bisa menggunakan bash loop polos:
Ini bekerja sangat baik di sini karena tidak ada celah dalam urutan. Kalau tidak, Anda mungkin ingin memeriksa apakah file sumber benar-benar ada.
Perhatikan bahwa berbeda dengan
for ((i=89000; i<=163022; ++i))
ekspansi brace yang menangani angka nol terkemuka sejak beberapa Bash merilis beberapa tahun yang lalu. Sebenarnya perubahan yang saya minta, jadi saya senang melihat kasus penggunaan untuk itu.Bacaan lebih lanjut: Perluasan Brace di halaman info Bash, khususnya bagian tentang
{x..y[..incr]}
.loop file
Pilihan lain adalah melompati glob yang sesuai, alih-alih melompati rentang integer yang dimaksud. Sesuatu seperti ini:
Sekali lagi ini adalah satu
mv
permintaan per file. Dan lagi loop adalah daftar elemen yang panjang, tetapi seluruh daftar tidak diteruskan sebagai argumen untuk suatu subproses, tetapi ditangani secara internal oleh bash, sehingga batas tidak akan menyebabkan masalah.Bacaan lebih lanjut: Ekspansi Parameter Shell di halaman info Bash, mendokumentasikan
${parameter/pattern/string}
antara lain.Jika Anda ingin membatasi rentang angka ke yang Anda berikan, Anda dapat menambahkan tanda centang untuk itu:
Di sini
${i##pattern}
menghapus pencocokan awalan terpanjangpattern
dari$i
. Awalan terpanjang itu didefinisikan sebagai apa saja, lalu garis bawah, lalu nol atau lebih nol. Yang terakhir ditulis sebagai*(0)
yang merupakan pola gumpal diperpanjang yang tergantung padaextglob
opsi yang ditetapkan. Menghapus angka nol di depan adalah penting untuk memperlakukan angka sebagai basis 10 bukan basis 8.+([0-9])
Argumen loop adalah glob yang diperluas, cocok dengan satu atau lebih digit, kalau-kalau Anda memiliki file di sana yang memulai yang sama tetapi tidak berakhir dengan jumlah.sumber
Salah satu cara untuk mengatasi
ARG_MAX
batas adalah dengan menggunakan built-in bash shellprintf
:Ex.
tapi
sumber
find
dalam direktori saat ini.
untuk semua file-type f
dan lakukan rename file yang ditemukan$1
dengan menggantiHBO_DPM
dengandmp
satu per satu-exec ... \;
ganti
echo
denganmv
untuk melakukan rename.sumber
Anda bisa menulis skrip python kecil, seperti:
Simpan itu sebagai file teks seperti
rename.py
dalam folder file, lalu dengan terminal di folder itu pergi:sumber
Anda dapat melakukannya file per file (mungkin butuh waktu) dengan
Seperti Perl yang
rename
digunakan dalam jawaban lain,rename.ul
juga memiliki opsi-n
atau--no-act
untuk pengujian.sumber
-n
bendera yang saya gunakan untuk pengujian dan menyarankan itu dapat digunakanrename.ul
juga.Saya melihat bahwa tidak ada yang mengundang teman baik saya
sed
ke pesta :).for
Loop berikut akan mencapai tujuan Anda:Ada banyak alat untuk pekerjaan seperti itu, pilih salah satu yang paling dimengerti untuk Anda. Yang ini sederhana dan mudah diubah sesuai dengan ini atau tujuan lain ...
sumber
$i
dalam substitusi perintah, tetapi tidak ada cara mudah untuk menangani baris baru yang tertinggal dalam nama file.Karena kita memberikan opsi, inilah pendekatan Perl.
cd
ke direktori target dan jalankan:Penjelasan
perl -e
: jalankan skrip yang diberikan oleh-e
.foreach(glob){}
: jalankan apa pun yang ada di{ }
pada setiap hasil dari glob.glob("sb_*")
: mengembalikan daftar semua file dan direktori di direktori saat ini yang namanya cocok dengan shell globsb*
.rename $_, s/_HBO_DPM_/_dpm_/r
: perl magic.$_
adalah variabel khusus yang menampung setiap elemen yang kita iterasi (dalamforeach
). Jadi di sini, itu akan menjadi setiap file yang ditemukan.s/_HBO_DPM_/_dpm_/
menggantikan kemunculan pertama_HBO_DPM_
dengan_dpm_
. Ini berjalan$_
secara default, sehingga akan berjalan di setiap nama file. The/r
berarti "berlaku pengganti ini untuk salinan string sasaran (nama file) dan mengembalikan string dimodifikasi.rename
Melakukan apa yang Anda harapkan: itu mengganti nama file Jadi semuanya akan mengubah nama nama file saat ini (.$_
) Untuk dirinya sendiri dengan_HBO_DPM_
diganti oleh_dpm_
.Anda dapat menulis hal yang sama dengan skrip yang diperluas (dan skrip yang lebih mudah dibaca):
sumber
Bergantung pada jenis penggantian nama yang Anda impikan, menggunakan vidir dengan pengeditan beberapa baris mungkin memuaskan.
Dalam kasus khusus Anda, Anda dapat memilih semua baris dalam editor teks Anda dan menghapus bagian _ " HBO" dari nama file dalam beberapa penekanan tombol.
sumber
vidir
?