Bagaimana cara mengubah ekstensi beberapa file?

168

Saya ingin mengubah ekstensi file dari *.txtmenjadi *.text. Saya mencoba menggunakan basenameperintah, tetapi saya mengalami kesulitan mengubah lebih dari satu file.

Ini kode saya:

files=`ls -1 *.txt`

for x in $files
do
    mv $x "`basename $files .txt`.text"
done

Saya mendapatkan kesalahan ini:

basename: too many arguments Try basename --help' for more information
afbr1201
sumber

Jawaban:

176

Langsung dari Greg's Wiki :

# Ganti nama semua * .txt ke * .text
untuk f di * .txt; melakukan
    mv - "$ f" "$ {f% .txt} .text"
Selesai

Lihat juga entri tentang mengapa Anda tidak perlu menguraikanls .

Sunting: jika Anda harus menggunakan basenamesintaks Anda adalah:

untuk f di * .txt; melakukan
    mv - "$ f" "$ (basename -" $ f ".txt) .text"
Selesai
jasonwryan
sumber
48
Ada beberapa sintaks Bash yang sedikit canggih yang digunakan di sini tanpa penjelasan. Saya harus ke Google banyak hal untuk memahami ini sepenuhnya. Untuk membantu orang lain di posisi saya, berikut adalah beberapa referensi tentang gumpalan ( *.txtsintaksis) , tanda hubung ganda-- , dan penggunaan simbol% ​​dalam ${}konstruk . Sampai sekarang saya belum pernah menemukan dua yang terakhir dan belum tahu apa yang sebenarnya terjadi dengan yang pertama.
Mark Amery
3
Lihatlah jawaban Matthias Braun di bawah ini - lebih sederhana, menyelesaikan hal yang sama.
btk
10
One linerfor f in *.txt; do mv -- "$f" "${f%.txt}.text"; done
Marçal Juan
1
Anda memiliki yang hilang; after text ".
Pétur Ingi Egilsson
2
@ PéturIngiEgilsson di baris kedua? Tidak, itu tidak wajib.
jasonwryan
132

Inilah cara saya mengubah semua ekstensi file di direktori saat ini di Debian.

rename "s/oldExtension/newExtension/" *.txt

(Ini adalah renameperintah Perl , bukan yang util-linux. Lihat Mengapa utilitas penggantian nama di Debian / Ubuntu berbeda dari yang ada di distribusi lain, seperti CentOS? )

Matthias Braun
sumber
10
Jauh lebih sederhana dari jawaban yang diterima, terima kasih!
btk
8
Di Mac saya bisa brew install renamedan membuatnya berfungsi.
Monkpit
3
dengan shell ikan yang dapat Anda lakukan rename "s/oldExtension/newExtension/" **.txtuntuk mengubah nama semua * .txt secara rekursif
Palmstrom
3
Ini akan gagal untuk footxt.txt. Gunakan ini sebagai gantinya: unix.stackexchange.com/questions/19654/…
wisbucky
7
Ketika file Anda tidak memiliki ekstensi apa pun dan Anda ingin menambahkannya:rename 's/$/.txt/' *
mkataja
35

Perintah sederhana, renamedariutil-linux , akan melakukan itu untuk Anda, itu menggantikan setiap kemunculan "txt" menjadi "teks" di semua file yang cocok dengan "* .txt":

rename txt text *.txt
lamwaiman1988
sumber
4
renamemengubah kejadian pertama, jadi lebih baik buat itu rename .txt .text, tetapi ini masih tidak akan selalu berhasil (misalnya berganti nama foo.txtx.bar.txtmenjadi foo.textx.bar.txt).
Gilles
12
Perlu dicatat bahwa tidak semua sistem memiliki versi nama yang sama; pada Debian dan teman-teman, renameperintahnya sebenarnya perl-renamedan menggunakan perl regexes. Untuk itu, perintah setara akan: rename 's/.txt/.text/' *.txt. Orang harus memeriksa man renamesistem mereka untuk mengetahui yang mana yang mereka miliki.
evilsoup
@evilsoup Itulah yang terjadi pada OSX, thx
Davi Lima
Ini juga berfungsi pada Cygwin (Windows)
andy
27
rename "s/oldExtension/newExtension/" *.txt

Di atas berfungsi dengan baik tetapi terbatas pada direktori saat ini. Coba perintah di bawah ini, yang fleksibel dengan sub-direktori. Ini akan mengganti nama semua .txtfile di bawah struktur direktori dengan ekstensi baru.

find . -name "*.txt" -exec rename 's/.txt$/.newext/' {} \;
Rahul
sumber
2
renamedapat menangani banyak file sebagai argumen, Anda dapat mempercepat banyak hal dengan menggunakan +alih-alih \;jika ada banyak file seperti itu
Anthon
Namun, ini adalah opsi yang berguna karena "* .txt" dapat membuka gulungan ke daftar argumen besar yang tidak didukung oleh shell.
Roman Shapovalov
1
"s / oldExtension / newExtension /" akan gagal untuk footxt.txt. Gunakan ini sebagai gantinya: unix.stackexchange.com/questions/19654/…
wisbucky
9
for f in *.txt
do
    [ -f "$f" ] && mv "$f" "${f%txt}text"
done
Pangeran John Wesley
sumber
9

Jawaban di sini referensi s/oldExtension/newExtension/salah. Jika Anda menggunakan s/txt/text/, Anda akan mengonversi footxt.txtke footext.txt, yang bukan yang Anda inginkan. Bahkan jika Anda menggunakan s/.txt/.text/, itu akan dikonversi footxt.txtmenjadi fo.text.txt.

Anda harus menggunakan \.untuk mencocokkan periode ( .akan cocok dengan karakter apa pun). Dan trailing $untuk mencocokkan ujung garis. Hanya ini yang akan cocok dengan ekstensi.

rename 's/\.txt$/.text/' *.txt

rename 's/\.old$/.new/' *.old
wisbucky
sumber
7

Berdasarkan jawaban @Prince John Wesley, berikut adalah skrip bash sederhana untuk mengubah semua ekstensi file di direktori saat ini dari ext1menjadi ext2. Juga menampilkan nama file yang diganti namanya.

#!/bin/bash
for f in *.$1
do
    [ -f "$f" ] && mv -v "$f" "${f%$1}$2"
done

Contoh penggunaan (dengan asumsi nama skripnya change-ext):

change-ext ext1 ext2
Dennis Golomazov
sumber
Untuk mengubah ekstensi file dalam direktori secara rekursif, ganti baris kedua ( for...) dengan dua baris: shopt -s globstardan for f in **/*.$1. Membutuhkan Bash 4+.
Dennis Golomazov
4

Alasan # 53 untuk beralih ke zsh:

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

Benitok
sumber
3

katakanlah file Anda tersebar di berbagai direktori, Dengan anggapan bahwa dirx adalah direktori induk Anda, ini dapat melakukan pekerjaan menggunakan find:

for f in `find /dirx -iname '*.txt' -type f -print`;do  mv "$f" ${f%.txt}.text; done
Arash
sumber
Bagaimana dengan tcsh ..
Josef Klimuk
2

Inilah yang bekerja untuk saya:

find . -name '*.txt' -exec rename 's/\.txt$/.text/' \{} \;
yegor256
sumber
1
TOLONG tambahkan. sebelum "teks"
danielmhanover
2

Kapan kamu

tidak memiliki ekstensi untuk file sumber

dan ekstensi target .text Anda akan melakukannya dengan cara ini -

for f in *; do mv -- "$f" "${f%.\*}.text"; done
nitinr708
sumber
1
Script bash-asli yang sangat baik. bekerja dengan baik! for f in *.html; do mv -- "$f" "${f%.\*}.pug"; done
TamusJRoyce
1

Jika Anda ingin tahu apa yang salah dalam versi Anda: Anda menggunakan $filesalih-alih $xpada perintah nama bas. Jadi ini seharusnya bekerja (belum diuji):

for x in *.txt
do
  mv "$x" "`basename '$x' .txt`.text"
done
daniel kullmann
sumber