Ganti nama massal, * versi nix


11

Saya sedang mencari cara untuk mengubah nama sejumlah besar file dengan nama yang sama, mirip seperti ini (pertanyaan yang berhubungan dengan Windows) kecuali bahwa saya menggunakan * nix (Ubuntu dan FreeBSD, secara terpisah). Singkatnya, saat menggunakan shell (Bash, CSH, dll.) Bagaimana cara mengubah nama massal sejumlah file sedemikian rupa, misalnya, file-file berikut:

Beethoven - Fur Elise.mp3
Beethoven - Moonlight Sonata.mp3
Beethoven - Ode to Joy.mp3
Beethoven - Rage Over the Lost Penny.mp3

akan diganti nama seperti ini?

Fur Elise.mp3
Moonlight Sonata.mp3
Ode to Joy.mp3
Rage Over the Lost Penny.mp3

Alasan saya ingin melakukan ini adalah bahwa kumpulan file ini akan berada di bawah direktori bernama "Beethoven" (yaitu awalan nama file '), dan memiliki informasi ini pada nama file itu sendiri akan menjadi berlebihan.

Jawaban:


12

Utilitas rename akan melakukan apa yang Anda inginkan.

Gunakan saja rename 's/Beethoven\ -\ //g' *.mp3


Bisakah Anda mengedit untuk memberikan tautan ke utilitas, atau apakah itu standar dalam kedua distribusi yang disebutkan (Ubuntu dan FreeBSD)?
Chris W. Rea

1
Muncul dengan Perl. Debian menggunakannya sebagai perintah ganti nama, jadi saya curiga Ubuntu juga. Ada perintah 'ganti nama' lain yang tidak berharga, jadi periksa halaman manual.
derobert

wow, sintaks ganti nama terlihat sangat mirip untuk menggantikan vim: D
Dzung Nguyen

port di / usr / ports / sysutils / rename bekerja dengan sempurna di FreeBSD
Josh W.

10

Seperti banyak hal dengan Linux / Unix, ada lebih dari satu cara untuk melakukannya!

Beberapa mungkin menggunakan mmv (mv massal).

Perintah rename, atau prename yang datang dengan beberapa paket Perl (Ubuntu dan Debian yang lebih baru) dapat melakukan ini juga.

prename 's/Beethoven\ -\ //g' Beethoven*.mp3

Perhatikan bahwa alat ganti nama pada Fedora 10 bukan program yang sama dengan ini dan bekerja secara berbeda. Ini adalah bagian dari paket yang berbeda, util-linux-ng dan dapat ditemukan di sini .

Saya sering hanya pergi ke shell untuk keluar dari kebiasaan (setelah semua alat seperti itu tidak selalu ada).

mkdir -p Beethoven
for x in Beethoven\ -\ *
do
mv "$x" Beethoven/"${x/Beethoven - /}"
done

Ini akan membuat direktori Beethoven, kemudian memindahkan file ke direktori / nama file, di mana nama file memiliki "Beethoven -" diganti dengan apa pun.

Sebagai ujian, sebelum:

$ ls
Beethoven - Fur Elise.mp3                 Beethoven - Ode to Joy.mp3
Beethoven - Moonlight Sonata.mp3          Beethoven - Rage Over the Lost Penny.mp3

Setelah:

$ ls Beethoven/
Fur Elise.mp3                 Ode to Joy.mp3
Moonlight Sonata.mp3          Rage Over the Lost Penny.mp3

4

Coba solusi ini, diimplementasikan menggunakan kombinasi grep dan rename. Ini dengan asumsi Anda memiliki banyak direktori yang perlu Anda ganti namanya. Jika hanya ada beberapa, saya akan menggunakan pendekatan manual, dengan pola "Artis -" yang dikodekan untuk masing-masing.

# Rename any mp3 files in the directory hierarchy of type "a - b.mp3" to "b.mp3"
find . -name "*.mp3" -exec rename -n -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;

Penjelasan menemukan :
The find perintah menemukan semua file dengan .mp3 ekstensi dalam hirarki file saat ini, dan menyebut argumen dilewatkan ke exec untuk masing-masing. Perhatikan bahwa di dalam -exec , {} merujuk ke argumen yang dilewati oleh find (path file + name). The \;memastikan ;akan diteruskan untuk mengganti nama dan bukannya menunjukkan akhir dari perintah find .

Perintah yang diberikan di atas memiliki saklar -n (tidak ada tindakan); maka itu hanya akan memberi tahu Anda apa yang akan terjadi jika Anda menjalankannya. Saya sarankan Anda menjalankan perintah ini tanpa -n beralih hanya setelah Anda menjalankannya sekali dan puas dengan hasil yang diusulkan.

Sekarang untuk regexp.

  • ^ cocok dengan mulai dari string.
  • $ cocok dengan akhir string.
  • . cocok dengan karakter apa pun.
  • *berarti nol atau lebih dari konstruk sebelumnya. mis. .*berarti nol atau lebih karakter.
  • \s singkatan karakter ruang apa pun.
  • \S singkatan karakter non-ruang.
  • Sesuatu dalam ()akan ditangkap dan disajikan sebagai $1, $2, tergantung pada posisinya.

Regexp:

  • Mencari struktur direktori opsional di awal, menangkap ini dalam $ 1: (.*/)
  • Lewati semuanya sampai " -":.*-
  • Menangkap sisa string, kecuali spasi awal dan akhir, dalam $ 2: (.*)
  • Tulis ulang file sebagai $ 1 $ 2, yang seharusnya "/path/to/file/""filename.mp3"

Inilah pengujian saya:

/tmp/test$ ls -R
.:
a  b  c  z-unknown.mp3

./a:
a3.mp3                 a - longer title3.mp3  c.mp3   disc2
a - longer title2.mp3  a - long title.mp3     disc 1  the band - the title.mp3

./a/disc 1:
a - title1.mp3  a - title2.mp3

./a/disc2:
a - title1.mp3  a - title2.mp3

./b:
cd - ab - title3.mp3  cd - title1.mp3  cd - title2.mp3  c.mp3

./c:
c-pony2.mp4  c - pony3.mp3  c - pony4.mp3  c-pony.mp3

/tmp/test$ find . -name "*.mp3" -exec rename -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;
./c/c-pony.mp3 renamed as ./c/pony.mp3
./c/c - pony4.mp3 renamed as ./c/pony4.mp3
./c/c - pony3.mp3 renamed as ./c/pony3.mp3
./z-unknown.mp3 renamed as ./unknown.mp3
./a/the band - the title.mp3 renamed as ./a/the title.mp3
./a/a - longer title2.mp3 renamed as ./a/longer title2.mp3
./a/a - longer title3.mp3 renamed as ./a/longer title3.mp3
./a/disc 1/a - title1.mp3 renamed as ./a/disc 1/title1.mp3
./a/disc 1/a - title2.mp3 renamed as ./a/disc 1/title2.mp3
./a/a - long title.mp3 renamed as ./a/long title.mp3
./a/disc2/a - title1.mp3 renamed as ./a/disc2/title1.mp3
./a/disc2/a - title2.mp3 renamed as ./a/disc2/title2.mp3
./b/cd - title1.mp3 renamed as ./b/title1.mp3
./b/cd - title2.mp3 renamed as ./b/title2.mp3
./b/cd - ab - title3.mp3 renamed as ./b/title3.mp3

/tmp/test$ ls -R
.:
a  b  c  unknown.mp3

./a:
a3.mp3  c.mp3  disc 1  disc2  longer title2.mp3  longer title3.mp3  long title.mp3  the title.mp3

./a/disc 1:
title1.mp3  title2.mp3

./a/disc2:
title1.mp3  title2.mp3

./b:
c.mp3  title1.mp3  title2.mp3  title3.mp3

./c:
c-pony2.mp4  pony3.mp3  pony4.mp3  pony.mp3

Regexp adalah bisnis yang rumit, dan saya telah membuat banyak kesalahan menulisnya, jadi saya akan menerima masukan tentang kurangnya jasa yang satu ini. Saya tahu saya menemukan beberapa pengujian ini.


1

Saya telah menyusun program Java baris perintah yang membuat pengubahan nama file (dan direktori) menjadi mudah, terutama untuk skrip. Ini gratis dan open source, sehingga Anda dapat memodifikasinya sesuai dengan isi hati Anda:

RenameWand
http://renamewand.sourceforge.net/

Beberapa contoh penggunaan yang relevan:

Pindahkan file formulir "<a> - <b>"ke direktori masing-masing "<a>":

java -jar RenameWand.jar  "<a> - <b>"  "<a>/<b>"

Sortir file berdasarkan waktu yang terakhir diubah, dan ganti namanya dengan angka 3 digit:

java -jar RenameWand.jar  "<a>"  "<3|#FT> <a>"

Atur ulang bagian nama file, dan ubah huruf besar-kecil:

java -jar RenameWand.jar  "<album> - <artist> - <song>.<ext>" 
                          "<artist.upper> <album.title> - <song>.<ext.lower>"

1

zmv Alat penamaan ulang zsh sangat bagus.

# zmv "programmable rename"
# Replace spaces in filenames with a underline
zmv '* *' '$f:gs/ /_'
# Change the suffix from *.sh to *.pl
zmv -W '*.sh' '*.pl'
# lowercase/uppercase all files/directories
$ zmv '(*)' '${(L)1}' # lowercase
$ zmv '(*)' '${(U)1}' # uppercase

Lebih banyak catatan di sini ...


0

Untuk kepala Penguin ini mudah dilakukan dalam skrip shell atau skrip AWK. Bagi kami manusia biasa, Anda mungkin ingin mencoba Midnight Commander. Ada di sebagian besar distribusi linux, dari tipe prompt shell mc -a. Anda dapat mengganti nama file menggunakan ekspresi reguler. Saya menggunakan artikel di GeekStuff http://www.thegeekstuff.com/2009/06/how-to-rename-files-in-group/ untuk membantu saya.


0

Berikut ini adalah contoh baris perintah sederhana. Saya memiliki kata "putih" di tengah-tengah nama sekelompok file png. Saya ingin mengeluarkannya dan meninggalkan hanya satu garis bawah. Ini berhasil:

for i in *.png; do mv "$i" "${i/white/}"; done

0

Gunakan vidir dan kemudian gunakan fitur editor Anda untuk menerapkan pola penggantian nama.

NAMA

vidir - edit direktori

RINGKASAN

vidir [--verbose] [direktori | file | -] ...

DESKRIPSI

vidir memungkinkan pengeditan konten direktori dalam editor teks. Jika tidak ada direktori yang ditentukan, direktori saat ini diedit.

Saat mengedit direktori, setiap item dalam direktori akan muncul pada baris bernomornya sendiri. Angka-angka ini adalah bagaimana vidir melacak item apa yang diubah. Hapus baris untuk menghapus file dari direktori, atau edit nama file untuk mengganti nama file. Anda juga dapat mengganti pasangan angka untuk bertukar nama file.

Perhatikan bahwa jika "-" ditetapkan sebagai direktori yang akan diedit, ia membaca daftar nama file dari stdin dan menampilkannya untuk diedit. Atau, daftar file dapat ditentukan pada baris perintah.

CONTOH

vidir vidir * .jpeg Penggunaan khusus.

temukan | vidir - Edit juga isi subdirektori. Untuk menghapus subdirektori, hapus semua kontennya dan subdirektori itu sendiri di editor.

temukan -type f | vidir - Edit semua file di bawah direktori dan subdirektori saat ini.

PENULIS

Joey Hess 2006-2010

Modifikasi oleh Magnus Woldrich 2011

HAK CIPTA

Hak Cipta 2006-2011 vidir "PENULIS" sebagaimana tercantum di atas.

Dilisensikan di bawah GNU GPL.


0

Pada * nix tanpa perl renametersedia

Pada beberapa * nix tidak ada rename yang tersedia, jadi perlu lakukan rename menggunakan beberapa metode lain. Beberapa tahun yang lalu saya menyarankan di zmvsini yang bagus, belum tentu tersedia juga.

Dengan menggunakan builtin dan sed, kita dapat dengan cepat menyiapkan skrip shell untuk melakukan ini yang memberi kita sintaksis yang sangat mirip dengan skrip perl rename, sementara kekurangan beberapa kesalahan penanganan kebaikan, itu menyelesaikan pekerjaan.

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      mv -v "$file" "$(sed $sed_pattern <<< $file)"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

Pemakaian

sedrename 's/Beethoven\ -\ //g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

Katakanlah kita juga ingin membuat folder target ...

Karena mvtidak membuat folder yang tidak bisa kita gunakan sedrenameseperti di sini, tapi itu perubahan yang cukup kecil, jadi saya pikir akan lebih baik untuk memasukkannya juga.

Kita memerlukan fungsi utilitas, abspath(atau jalur absolut) sehingga kita dapat membuat folder target untuk pola sed / rename yang mencakup struktur folder baru.

abspath () { case "$1" in
               /*)printf "%s\n" "$1";;
               *)printf "%s\n" "$PWD/$1";;
             esac; }

Ini akan memastikan kami mengetahui nama folder target kami. Saat kami mengganti nama, kami harus menggunakannya pada nama file target.

# generate the rename target
target="$(sed $sed_pattern <<< $file)"

# Use absolute path of the rename target to make target folder structure
mkdir -p "$(dirname $(abspath $target))"

# finally move the file to the target name/folders
mv -v "$file" "$target"

Berikut skrip sadar folder lengkap ...

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      target="$(sed $sed_pattern <<< $file)"
      mkdir -p "$(dirname $(abspath $target))"
      mv -v "$file" "$target"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

Tentu saja, itu masih berfungsi ketika kita tidak memiliki folder target spesifik juga.

Jika kami ingin memasukkan semua lagu ke dalam folder, ./Beethoven/kami dapat melakukan ini:

Pemakaian

sedrename 's|Beethoven - |Beethoven/|g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

Putaran bonus ...

Menggunakan skrip ini untuk memindahkan file dari folder ke satu folder:

Dengan asumsi kami ingin mengumpulkan semua file yang cocok, dan menempatkannya di folder saat ini, kami dapat melakukannya:

sedrename 's|.*/||' **/*.mp3

before:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

after:

./Beethoven/ # (now empty)
./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

Perhatikan pada pola sed regex

Aturan pola sed reguler berlaku dalam skrip ini, pola ini bukan PCRE (Perl Regular Regular Expressions). Anda bisa menambahkan sintaks ekspresi reguler yang diperluas, menggunakan salah satu sed -ratau sed -E tergantung pada platform Anda.

Lihat patuh POSIX man re_formatuntuk deskripsi lengkap dari pola dasar dasar dan regexp diperluas.

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.