Làm cách nào để thay đổi phần mở rộng của nhiều tệp?


168

Tôi muốn thay đổi một phần mở rộng tập tin từ *.txtđến *.text. Tôi đã thử sử dụng basenamelệnh, nhưng tôi gặp khó khăn khi thay đổi nhiều hơn một tệp.

Đây là mã của tôi:

files=`ls -1 *.txt`

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

Tôi đang gặp lỗi này:

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

Một số ý tưởng tại peteryu.ca/tutorials/shellscripting/batch_rename cũng vậy
Nemo

Câu trả lời:


176

Trực tiếp từ Wiki của Greg :

# Đổi tên tất cả * .txt thành * .text
cho f trong * .txt; làm
    mv - "$ f" "$ {f% .txt} .text"
làm xong

Cũng xem mục tại sao bạn không nên phân tích cú phápls .

Chỉnh sửa: nếu bạn phải sử dụng basenamecú pháp của bạn sẽ là:

cho f trong * .txt; làm
    mv - "$ f" "$ (tên cơ sở -" $ f ".txt) .text"
làm xong

48
Có một số cú pháp Bash hơi tiên tiến được sử dụng ở đây mà không cần giải thích. Tôi đã phải Google nhiều điều để hiểu điều này một cách đầy đủ. Để giúp những người khác ở vị trí của tôi, đây là một số tài liệu tham khảo về các khối ( *.txtcú pháp) , dấu gạch ngang kép--sử dụng ký hiệu% trong ${}cấu trúc . Cho đến bây giờ tôi chưa bao giờ gặp hai người sau và không biết chuyện gì đang thực sự xảy ra với người trước.
Đánh dấu Amery

3
Hãy xem câu trả lời của Matthias Braun dưới đây - đơn giản hơn nhiều, hoàn thành điều tương tự.
btk

10
Một lớp lótfor f in *.txt; do mv -- "$f" "${f%.txt}.text"; done
Marçal Juan

1
Bạn có một mất tích; sau văn bản ".
Pétur Ingi Egilsson

2
@ PéturIngiEgilsson trên dòng thứ hai? Không, nó không bắt buộc.
jasonwryan

132

Đây là cách tôi thay đổi tất cả các phần mở rộng tệp trong thư mục hiện tại trên Debian.

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

(Đây là renamelệnh Perl , không phải lệnh util-linux. Xem tại sao tiện ích đổi tên trên Debian / Ubuntu khác với tiện ích trên các bản phân phối khác, như CentOS? )


10
Đơn giản hơn nhiều so với câu trả lời được chấp nhận, cảm ơn bạn!
btk

8
Trên Mac tôi đã có thể brew install renamevà làm cho nó hoạt động.
Monkpit

3
với vỏ cá bạn có thể làm rename "s/oldExtension/newExtension/" **.txtđể đổi tên tất cả * .txt đệ quy
Palmstrom

3
Điều này sẽ thất bại cho footxt.txt. Sử dụng cái này thay thế: unix.stackexchange.com/questions/19654/ cấp
wvducky

7
Khi tệp của bạn không có bất kỳ tiện ích mở rộng nào và bạn muốn thêm một phần:rename 's/$/.txt/' *
mkataja

35

Một lệnh đơn giản, renametừutil-linux , sẽ làm điều đó cho bạn, nó thay thế mọi lần xuất hiện của "txt" thành "văn bản" trong tất cả các tệp khớp "* .txt":

rename txt text *.txt

4
renamethay đổi lần xuất hiện đầu tiên, vì vậy tốt hơn là thực hiện điều đó rename .txt .text, nhưng điều này vẫn không phải lúc nào cũng hoạt động (ví dụ: nó đổi tên foo.txtx.bar.txtthành foo.textx.bar.txt).
Gilles

12
Cần lưu ý rằng không phải tất cả các hệ thống đều có cùng một phiên bản đổi tên; trên Debian và bạn bè, renamelệnh thực sự perl-renamevà sử dụng các biểu thức perl. Đối với điều đó, lệnh tương đương sẽ là : rename 's/.txt/.text/' *.txt. Mọi người nên kiểm tra man renametrên hệ thống của họ để tìm ra cái nào họ có.
evilsoup

@evilsoup Đó là trường hợp của OSX, thx
Davi Lima

Điều này cũng hoạt động trên Cygwin (Windows)
andy

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

Ở trên hoạt động tốt nhưng giới hạn trong thư mục hiện tại. Hãy thử lệnh dưới đây, linh hoạt với các thư mục con. Nó sẽ đổi tên tất cả .txtcác tệp theo cấu trúc thư mục với một phần mở rộng mới.

find . -name "*.txt" -exec rename 's/.txt$/.newext/' {} \;

2
renamecó thể xử lý nhiều tệp làm đối số, bạn có thể tăng tốc mọi thứ lên rất nhiều bằng cách sử dụng +thay vì \;nếu có nhiều tệp như vậy
Anthon

Tuy nhiên, đây là một tùy chọn hữu ích vì "* .txt" có thể hủy đăng ký vào danh sách đối số lớn không được hỗ trợ bởi trình bao.
Roman Shapovalov

1
"s / oldExtension / newExtension /" sẽ không thành công footxt.txt. Sử dụng cái này thay thế: unix.stackexchange.com/questions/19654/ trên
wvducky


9

Các câu trả lời ở đây tham khảo s/oldExtension/newExtension/là sai. Nếu bạn sử dụng s/txt/text/, bạn sẽ chuyển đổi footxt.txtthành footext.txt, đó không phải là những gì bạn muốn. Ngay cả khi bạn sử dụng s/.txt/.text/, điều đó sẽ chuyển đổi footxt.txtthành fo.text.txt.

Bạn phải sử dụng \.để khớp với khoảng thời gian ( .sẽ khớp với bất kỳ ký tự nào). Và dấu vết $để phù hợp với cuối dòng. Chỉ điều này sẽ phù hợp với phần mở rộng.

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

rename 's/\.old$/.new/' *.old

7

Dựa trên câu trả lời @Prince John Wesley, đây là một tập lệnh bash đơn giản để thay đổi tất cả các phần mở rộng của các tệp trong thư mục hiện tại từ ext1sang ext2. Cũng xuất ra tên của các tập tin được đổi tên.

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

Ví dụ sử dụng (giả sử tên của tập lệnh là change-ext):

change-ext ext1 ext2

Để thay đổi phần mở rộng của tệp trong thư mục theo cách đệ quy, thay thế dòng thứ hai ( for...) bằng hai dòng: shopt -s globstarfor f in **/*.$1. Yêu cầu Bash 4+.
Dennis Golomazov

4

Lý do # 53 để chuyển sang zsh:

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


3

giả sử các tệp của bạn nằm rải rác trong thư mục khác nhau, Giả sử dirx là thư mục mẹ của bạn, điều này có thể thực hiện công việc bằng cách sử dụng find:

for f in `find /dirx -iname '*.txt' -type f -print`;do  mv "$f" ${f%.txt}.text; done

Thế còn tcsh ..
Josef Klimuk 15/07/18

2

Đây là những gì làm việc cho tôi:

find . -name '*.txt' -exec rename 's/\.txt$/.text/' \{} \;

1
XIN thêm a. trước "văn bản"
danielmhanover

2

Khi bạn

không có phần mở rộng cho các tệp nguồn

và phần mở rộng mục tiêu là .text bạn sẽ làm theo cách này -

for f in *; do mv -- "$f" "${f%.\*}.text"; done

1
Kịch bản bash-bản địa tuyệt vời. làm việc tuyệt vời for f in *.html; do mv -- "$f" "${f%.\*}.pug"; done
TamusJRoyce

1

Trong trường hợp bạn muốn biết điều gì đã xảy ra trong phiên bản của mình: Bạn đã sử dụng $filesthay vì $xtrong lệnh basename. Vì vậy, điều này sẽ làm việc (chưa được kiểm tra):

for x in *.txt
do
  mv "$x" "`basename '$x' .txt`.text"
done
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.