Bagaimana cara saya mengganti nama ekstensi untuk banyak file?

480

Dalam sebuah direktori, saya memiliki banyak *.htmlfile. Saya ingin mengubah nama mereka semua menjadi*.txt

Bagaimana saya bisa melakukan itu? Saya menggunakan bash shell.

bmw0128
sumber

Jawaban:

382

Untuk solusi yang lebih baik (hanya dengan fungsi bash, sebagai lawan dari panggilan eksternal), lihat salah satu jawaban lainnya .


Berikut ini akan dilakukan dan tidak memerlukan sistem untuk memiliki renameprogram (meskipun Anda paling sering memiliki ini pada sistem):

for file in *.html; do
    mv "$file" "$(basename "$file" .html).txt"
done

EDIT: Seperti yang ditunjukkan dalam komentar, ini tidak berfungsi untuk nama file dengan spasi di dalamnya tanpa penawaran yang tepat (sekarang ditambahkan di atas). Ketika bekerja murni pada file Anda sendiri yang Anda tahu tidak memiliki spasi dalam nama file ini akan berfungsi tetapi setiap kali Anda menulis sesuatu yang dapat digunakan kembali di lain waktu, jangan lewati kutipan yang tepat.

Mikael Auno
sumber
47
Alternatif, tanpa nama & tanda kutip: mv "$ {file}" "$ {file /%. Html / .txt}" (lihat man bash, Perluasan Parameter untuk detail)
Rodrigo Queiro
7
Hanya bagus jika semua file ada di direktori saat ini, tentu saja, karena nama bas mengupas bagian pathname. Berhati-hatilah!
Jonathan Leffler
6
Solusi ini buruk, bukan hanya karena lambat tetapi karena tidak bekerja dengan nama file dengan spasi di dalamnya. Anda harus SELALU melakukan kutipan yang tepat dalam skrip bash. mv "$ file" "$ (nama file" $ file ".html)". txt akan jauh lebih baik. Tapi tetap saja, mv "$ file" "$ {files% .html} .txt" jauh lebih baik.
Balázs Pozsár
8
di windows yang baru saja Anda lakukanren *.a *.b
Muhammad Umer
2
Minimal, gunakan POSIX- $()bukan sintaks backtick warisan. Meningkatkan keterbacaan, dan membuat sintaks jauh lebih tidak ambigu ketika Anda memiliki karakter yang perlu backslash-escape untuk menjadi literal di dalam substitusi perintah dengan yang terakhir.
Charles Duffy
669

Jika menggunakan bash, tidak perlu untuk perintah eksternal seperti sed, basename, rename, expr, dll.

for file in *.html
do
  mv "$file" "${file%.html}.txt"
done
ghostdog74
sumber
12
Dan jika Anda tidak tahu ekstensi file yang dapat Anda gunakan "${file%.*}.txt", tetapi ini bisa berbahaya untuk file tanpa ekstensi sama sekali.
Jess
1
Catatan untuk siapa pun yang mengalami kesulitan untuk bekerja seperti ini: perhatikan bahwa tidak ada $di dalam kurung kurawal!
doug65536
5
Saya perlu cara untuk secara permanen favorit / bookmark jawaban ini, saya tidak pernah ingat sintaks yang tepat dan saya akhirnya googling untuk itu
boliva
7
@danip Konstruk persen-tanda-dalam-braket menghapus karakter di bagian akhir. Ada juga konstruksi hash-dalam-braket yang menghapus karakter dari awal. Periksa: tldp.org/LDP/abs/html/parameter-substitution.html#PSUB2
4
Jawaban pertukaran tumpukan lain (yang tidak dapat saya temukan!) Menyarankan ini, tetapi juga menggunakan --"operator": mv - "$ file" "$ {file% .html} .txt" Operator itu mencegah nama file yang dimulai dengan a '-' agar tidak diuraikan oleh mv sebagai argumen.
rcreswick
191
rename 's/\.html$/\.txt/' *.html

melakukan apa yang Anda inginkan.

Amber
sumber
Saya tidak berpikir Anda dapat menggunakan regex literal di bash seperti yang Anda sarankan - shell mana yang Anda gunakan?
DaveR
1
Saya menggunakan terminal Mac
bmw0128
Inilah halaman manual untuk versi rename di Ubuntu: unixhelp.ed.ac.uk/CGI/man-cgi?rename
Amber
rename adalah perintah pada beberapa sistem. Saya memiliki skrip Perl (aslinya dari buku Unta pertama) yang berfungsi. Ada juga program GNU dengan nama yang sama yang melakukan pekerjaan yang kira-kira sama. Mac saya tidak memiliki perintah 'ganti nama' yang disediakan sistem - atau tidak ada pada PATH saya (yang cukup komprehensif).
Jonathan Leffler
Ada rumus ganti nama di Homebrew.
revprez
112

Ini bekerja untuk saya di OSX dari .txt ke .txt_bak

find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;
Steven Lizarazo
sumber
4
Berfungsi dengan baik di linux juga.
Diziet
Ini selain titik, tapi untuk pergi dari .txtke .txt_bakAnda hanya harus concatenate _bak;)
corwin.amber
3
Ini bagus untuk mengganti nama secara rekursif
leachryanb
Bagus! (di bawah Ubuntu 16.04) Kasing penggunaan praktis saya, mengganti nama semua .scssmenjadi .sass(setelah konversi di tempat ...):find . -name '*.scss' -exec sh -c 'mv "$0" "${0%.scss}.sass"' {} \;
Frank Nocke
2
ini bekerja dengan +6000 file, ganti nama yang dilaporkan "daftar argumen terlalu panjang"
Tony Cronin
94

Anda ingin menggunakan rename:

rename -S .html .txt *.html

Ini sesuai keinginan Anda - ekstensi akan diubah dari .htmlmenjadi .txtuntuk semua file yang cocok *.html.

Catatan: Greg Hewgill dengan benar menunjukkan ini bukan bash bawaan; dan merupakan perintah Linux yang terpisah. Jika Anda hanya butuh sesuatu di Linux, ini akan berfungsi dengan baik; jika Anda membutuhkan sesuatu yang lebih lintas platform maka lihatlah salah satu jawaban lainnya.

DaveR
sumber
7
Meskipun ini adalah solusi yang baik, renameprogram ini tidak terkait dengan bashdan juga tidak tersedia di semua platform. Saya hanya melihatnya di Linux.
Greg Hewgill
15
"$ rename .html .txt * .html" menghasilkan ... kesalahan sintaks pada (eval 1) baris 1, dekat "."
Amber
8
Sintaks yang benar adalah rename -S .html .text *.htmldi mana -Ssingkatan--subst-all
Marek Sebera
8
brew install rename
Nick
4
Ganti nama @GregHewgill tersedia untuk Mac OS dengan HomeBrew
CodeBrauer
36

Di Mac ...

  1. Instal ganti nama jika Anda belum:brew install rename
  2. rename -S .html .txt *.html
izilotti
sumber
15

Untuk Pengguna Ubuntu:

rename 's/\.html$/\.txt/' *.html
Bheru Lal Lohar
sumber
Ini tidak rekursif, tetapi berhasil untuk saya di Ubuntu 14.04.
Max Wallace
9

Ini adalah solusi paling licin yang saya temukan yang bekerja pada OSX dan Linux, dan itu bekerja dengan baik dengan git juga!

find . -name "*.js" -exec bash -c 'mv "$1" "${1%.js}".tsx' - '{}' \;

dan dengan git:

find . -name "*.js" -exec bash -c 'git mv "$1" "${1%.js}".tsx' - '{}' \;

bdombro
sumber
8

Ini adalah contoh dari perintah rename:

rename -n s/\.htm$/\.html/’ *.htm

-N berarti bahwa ini merupakan percobaan dan tidak akan benar-benar mengubah file apa pun. Ini akan menampilkan daftar file yang akan diubah namanya jika Anda menghapus -n. Dalam kasus di atas, itu akan mengkonversi semua file di direktori saat ini dari ekstensi file .htm ke .html.

Jika output dari uji coba di atas tampak ok maka Anda dapat menjalankan versi final:

rename -v s/\.htm$/\.html/’ *.htm

-V adalah opsional, tetapi itu ide yang baik untuk memasukkannya karena itu adalah satu-satunya catatan Anda akan memiliki perubahan yang dibuat oleh perintah rename seperti yang ditunjukkan pada contoh output di bawah ini:

$ rename -v 's/\.htm$/\.html/' *.htm
3.htm renamed as 3.html
4.htm renamed as 4.html
5.htm renamed as 5.html

Bagian rumit di tengah adalah subtitusi Perl dengan ekspresi reguler, disorot di bawah ini:

rename -v s/\.htm$/\.html/’ *.htm
A A
sumber
6

Pertanyaan ini secara eksplisit menyebutkan Bash, tetapi jika Anda memiliki ZSH tersedia, itu cukup sederhana:

zmv '(*).*' '$1.txt'

Jika Anda zsh: command not found: zmvmenjalankannya, jalankan saja:

autoload -U zmv

Lalu coba lagi.

Terima kasih untuk artikel asli ini untuk tip tentang zmv.

Michael Leonard
sumber
4

Setelah merayapi situs web orang lain, saya berakhir dengan ribuan file kehilangan ekstensi .html, melintasi pohon subdirektori yang luas.

Untuk mengganti nama mereka semua dalam satu pengambilan, kecuali file yang sudah memiliki ekstensi .html (kebanyakan dari mereka tidak punya sama sekali), ini bekerja untuk saya:

cd wwwroot
find . -xtype f \! -iname *.html   -exec mv -iv "{}"  "{}.html"  \;  # batch rename files to append .html suffix IF MISSING

Dalam kasus OP, saya mungkin memodifikasi sedikit, hanya mengubah nama file * .txt, seperti:

find . -xtype f  -iname *.txt   -exec filename="{}"  mv -iv ${filename%.*}.{txt,html}  \; 

Rusak (waktu tidur!):

-iname * .txt
- Artinya HANYA mempertimbangkan file yang sudah berakhiran .txt

mv -iv "{}. {txt, html}" - Ketika find melewati {} sebagai nama file, $ {filename%. *} mengekstrak nama dasarnya tanpa ekstensi apa pun untuk membentuk parameter ke mv . bash mengambil {txt, html} untuk menulis ulang sebagai dua parameter sehingga perintah terakhir berjalan sebagai:mv -iv "filename.txt" "filename.html"

Perbaiki yang diperlukan: menangani spasi di nama file

Marcos
sumber
4

The perintahmmv tampaknya melakukan tugas ini sangat efisien pada sejumlah besar file (puluhan ribu dalam satu detik). Misalnya, untuk mengganti nama semua .xmlfile menjadi .htmlfile, gunakan ini:

mmv ";*.xml" "#1#2.html"

yang ;akan cocok jalan, yang *akan cocok nama file, dan ini disebut sebagai #1dan #2dalam nama pengganti.

Jawaban berdasarkan execatau pipa terlalu lambat atau gagal pada sejumlah besar file.

Roko Mijic
sumber
3

Coba ini

rename .html .txt *.html 

pemakaian:

rename [find] [replace_with] [criteria]
P Sreedhar
sumber
3

Agak terlambat ke pesta. Anda bisa melakukannya dengan xargs:

ls *.html | xargs -I {} sh -c 'mv $1 `basename $1 .html`.txt' - {}

Atau jika semua file Anda ada di folder tertentu

ls folder/*.html | xargs -I {} sh -c 'mv $1 folder/`basename $1 .html`.txt' - {}
esp
sumber
3
Tidak. Jangan uraikanls . Perintah ini konyol: tidak berguna menggunakan glob dengan ls, bukannya langsung menggunakan glob. Ini akan pecah dengan nama file yang mengandung spasi, tanda kutip dan (karena kurangnya tanda kutip) karakter glob.
gniourf_gniourf
FYI, artikel tertaut Anda berisi catatan yang diperbarui yang mengatakan file LS yang lebih baru 'shell escape' jika dicetak ke terminal. ' Maksud Anda masih merupakan aturan praktis yang baik.
Katastic Voyage
3

Ini adalah cara yang baik untuk memodifikasi beberapa ekstensi sekaligus:

for fname in *.{mp4,avi}
do
   mv -v "$fname" "${fname%.???}.mkv"
done

Catatan: berhati-hatilah pada ukuran ekstensi agar sama (the ???)

Nick De Greek
sumber
2

Bagus & sederhana!

find . -iname *.html  -exec mv {} "$(basename {} .html).text"  \;
Deano
sumber
2

Jika Anda lebih suka PERL, ada skrip PERL pendek (awalnya ditulis oleh Larry Wall, pembuat PERL) yang akan melakukan persis apa yang Anda inginkan di sini: tips.webdesign10.com/files/rename.pl.txt .

Sebagai contoh Anda, yang berikut ini harus melakukan trik:

rename.pl 's/html/txt/' *.html
dudusan
sumber
2
Pertanyaan ini sudah dijawab dan diterima sejak lama dan sepertinya jawaban Anda tidak membawa apa-apa lebih dari apa yang sudah dikatakan.
ChristopheLec
1
1 sejak itu adalah skrip Larry Wall (dimodifikasi oleh Robin Barker). Url terakhir yang tersedia adalah ini: tips.webdesign10.com/files/rename.pl.txt
loretoparisi
1

Demikian pula dengan apa yang disarankan sebelumnya, ini adalah bagaimana saya melakukannya:

find . -name '*OldText*' -exec sh -c 'mv "$0" "${0/OldText/NewText}"' {} \;

Saya pertama kali divalidasi dengan

find . -name '*OldText*' -exec sh -c 'echo mv "$0" "${0/OldText/NewText}"' {} \;
Carl Bosch
sumber
1

Satu baris, tanpa loop:

ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}

Contoh:

$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.json  ac8453e2-0d82-4d43-b80e-205edb754700.json
$ ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.txt  ac8453e2-0d82-4d43-b80e-205edb754700.txt
Christian Bongiorno
sumber
+1 untuk menunjukkan cara bash-only yang tidak bergantung pada pencocokan ekstensi yang ada secara tepat. Ini berfungsi untuk ekstensi input apa pun, baik panjangnya 3 karakter atau 4 karakter atau lebih
Ciprian Tomoiagă
0

Sayangnya itu tidak sepele untuk dilakukan dengan mudah. Anda mungkin perlu sedikit sihir expr.

for file in *.html; do echo mv -- "$file" "$(expr "$file" : '\(.*\)\.html').txt"; done

Hapus gema begitu Anda senang itu melakukan apa yang Anda inginkan.

Sunting: basename mungkin sedikit lebih mudah dibaca untuk kasus khusus ini, meskipun exprsecara umum lebih fleksibel.

CB Bailey
sumber
Meskipun ini mungkin bukan jawaban terbaik untuk pertanyaan itu, itu untuk saya! Saya membutuhkan cara untuk mengubah nama hanya dalam string seluruh path, bukan hanya nama file. Terima kasih untuk posting!
donat
0

Inilah yang saya gunakan untuk mengganti nama .edgefile.blade.php

for file in *.edge; do     mv "$file" "$(basename "$file" .edge).blade.php"; done

Bekerja seperti pesona.

Nixon Kosgei
sumber
0

Anda juga dapat membuat fungsi di Bash, menambahkannya ke .bashrcatau sesuatu, lalu menggunakannya di mana pun Anda inginkan.

change-ext() {
    for file in *.$1; do mv "$file" "$(basename "$file" .$1).$2"; done
}

Pemakaian:

change-ext css scss

Sumber kode dalam fungsi: https://stackoverflow.com/a/1224786/6732111

J Kluseczka
sumber
0

Ganti nama ekstensi file untuk semua file di bawah direktori dan sub direktori saat ini tanpa paket lain (hanya gunakan skrip shell):

  1. Buat skrip shell di rename.shbawah direktori saat ini dengan kode berikut:

    #!/bin/bash
    
    for file in $(find . -name "*$1"); do
      mv "$file" "${file%$1}$2"
    done
  2. Jalankan dengan ./rename.sh .old .new.

    Misalnya. ./rename.sh .html .txt

Neo Liu
sumber