Cara mengganti nama banyak file dalam direktori pada saat yang bersamaan


12

Saya memiliki direktori say /var/tmp/abcyang memiliki 4 file:

12345-ram-3e3r5-io9490-89adu9.csv
45434-dam-qwe35-to9490-43adu9.csv
11234-cam-yy3r5-ro9490-85adu9.csv
14423-sam-hh3r5-uo9490-869du9.csv

Saya ingin mengubah nama semua file CSV (temukan semua file & ganti nama) dengan cara sesingkat mungkin (mungkin satu-liner) untuk ini:

XXXXX-ram-3e3r5-io9490-89adu9.csv
XXXXX-dam-qwe35-to9490-43adu9.csv
XXXXX-cam-yy3r5-ro9490-85adu9.csv
XXXXX-sam-hh3r5-uo9490-869du9.csv

Jawaban:


15

rename -n 's/(\w+)/XXXXX/' *.csv

hapus -nsaat senang.


2
Untuk versi yang sesuai rename. Saya berasumsi ini adalah Larry Wall's rename, dari renamepaket di Debian dan turunannya (dan IIRC prenamepada sistem persuasi RedHat). Alat yang sangat berguna.
xenoid

2
perl-renamedi arch linux
lesmana

1
@SHawarden, saya sudah mencoba menjalankan perintah dan membaca bagian halaman man yang relevan untuk memahami pola ganti, tetapi ketika menambahkan verboseflag, tidak menghasilkan apa-apa dan tidak melakukan perubahan nama file, meskipun jalur saat ini memiliki file dengan nama yang mirip dengan 12345_foo.csv. Apakah saya harus melakukan tugas tambahan untuk membuatnya berfungsi (saat ini di Fedora 30)? Ini adalah pendekatan yang lebih bersih daripada perulangan. Terima kasih sebelumnya!
danieldeveloper001

3
@ danieldeveloper001 Apakah Anda menggunakan renameatau prename? Lihat komentar saya di atas. man {the command}daftar penulis di bagian akhir.
xenoid

2
Ini hanya bekerja pada sistem yang diturunkan dari Debian. Sistem turunan Fedora memiliki renameperintah yang sama sekali berbeda ; lihat unix.stackexchange.com/a/238862/135943
Wildcard

11

Mencoba:

for f in *.csv; do mv -i -- "$f" "XXXXX-${f#*-}"; done

Bagaimana itu bekerja:

  • for f in *.csv; do

    Ini memulai loop atas semua *.csvfile.

  • mv -i -- "$f" "XXXXX-${f#*-}"

    Ini mengganti nama file seperti yang Anda inginkan, bertanya secara interaktif sebelum menimpa file apa pun.

  • done

    Ini menandai akhir dari loop.

Contoh:

$ ls -1
11234-cam-yy3r5-ro9490-85adu9.csv
12345-ram-3e3r5-io9490-89adu9.csv
14423-sam-hh3r5-uo9490-869du9.csv
45434-dam-qwe35-to9490-43adu9.csv
$ for f in *.csv; do mv -i -- "$f" "XXXXX-${f#*-}"; done
$ ls -1
XXXXX-cam-yy3r5-ro9490-85adu9.csv
XXXXX-dam-qwe35-to9490-43adu9.csv
XXXXX-ram-3e3r5-io9490-89adu9.csv
XXXXX-sam-hh3r5-uo9490-869du9.csv

4

Saya menyukai tantangan kecil yang telah Anda posting, jadi inilah solusi saya. Saya mengasumsikan bahwa semua file Anda dimulai dengan 5 karakter numerik, jadi gunakan perintah cut untuk mengganti file angka awal dengan "XXXXX".

Di bawah ini, file sebelum perintah.

-rw-rw-r--. 1 daniel daniel 0 May 13 23:18 11111_bar_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 12345_baz_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 67890_foo_file.xml

Di bawah ini, perintah one liner.

for src in *.csv; do dst=XXXXX$(echo $src| cut -c6-); mv $src $dst; done;

Di bawah, file setelah perintah.

-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 67890_foo_file.xml
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 XXXXX_bar_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 23:18 XXXXX_baz_file.csv

Itukah yang kamu cari? :)

Referensi:

Looping melalui output perintah di bash

Substring dalam bash


2
Bash dapat melakukan manipulasi string semacam ini, tidak perlu melakukan proses baru untuk masing-masing, tolong jawaban yang lain tentang caranya.
chx

1
@ chx, sudah melihat jawaban lain dan memperoleh sedikit pengetahuan darinya, tapi terima kasih telah menunjukkannya. Bisakah Anda jelaskan lebih lanjut no need to fork a new process for each?
danieldeveloper001

3
cutadalah biner terpisah ( /usr/bin/cut) dan menjalankannya menghabiskan lebih banyak sumber daya daripada menggunakan shell built in.
chx

2
Saya mengerti, itu sebenarnya penting jika tujuannya mengganti nama banyak file. Terimakasih atas klarifikasinya!
danieldeveloper001

1

tidak ada garpu:

ls | perl -lne '$suf=substr($_,6); rename $_, "XXXXX-$suf"'

Ketika Anda menggunakan loop shell, mvgarpu sekali per file. PerlrenamePerintah tidak.

(Perintah rename Perl memiliki beberapa batasan, tetapi dalam kasus khusus ini pembatasan tersebut tidak berlaku.)

Adapun renameperintah yang ditunjukkan sebelumnya, ya itu berhasil, tetapi kemudian Anda memiliki semua kebingungan antara dua jenis nama yang berbeda dan seterusnya. Jika Anda memiliki yang benar, bagus, tetapi jika tidak, ini juga berfungsi.

Jika Anda tidak memiliki perintah perl-rename dan tidak dapat menginstalnya, Anda bisa melakukan ini:

ls | perl -lne '$old=$_; s/(\w+)/XXXXX/; rename $old, $_'

Seperti yang Anda lihat, ini menggunakan substitusi yang sama seperti yang ditunjukkan pada jawaban teratas. Tentu saja perl-rename memiliki lonceng lainnya dan peluit (jawaban atas disebutkan, -nsudah, kemudian ada -0, -fdan sebagainya), dan lebih dari mereka yang Anda butuhkan, semakin Anda harus menginstal bahwa alih-alih rolling Anda sendiri dengan cara ini .


Implementasi biasa dari pipa akan memiliki garpu.
muru

Maksud saya, "tidak akan memotong satu kali per file untuk diganti namanya", tidak seperti bahkan shell, di mana "mv" memecah / usr / bin / mv atau apa pun. Ini karena perintah "rename" adalah perintah internal perl yang secara langsung memanggil rename () di libc. Tentu saja ada beberapa batasan, tetapi dalam contoh khusus ini pembatasan itu tidak berlaku.
sitaram

1
Itu juga berlaku untuk renameperintah ( jawaban atas , juga menggunakan Perl), jadi mungkin Anda harus menambahkan sedikit penjelasan lebih dari sekadar "tanpa garpu" untuk jawabannya.
muru
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.