Thay thế dấu chấm trong tên tệp bằng dấu gạch dưới trừ phần mở rộng


9

Ai đó có thể đề nghị về cách đổi tên tên tệp:

head.body.date.txt

Đến:

head_body_date.txt

Có một tuyên bố dòng duy nhất để thực hiện đổi tên trong Unix ?


9
Bạn có cho rằng đó .tar.gzlà một phần mở rộng? Ngoài ra, chào mừng bạn đến với U & L!
EKons

2
Bạn có thực sự có nghĩa là Unix trái ngược với Linux? Mà Unix?
terdon

1
Câu trả lời rõ ràng là mv head.body.date.txt head_body_date.txt. Nếu bạn có những hạn chế hoặc ví dụ thực tế khác, thì vui lòng cập nhật câu hỏi của bạn với những điều này. Hiện tại, vẫn chưa rõ liệu câu hỏi có đề cập đến một tệp có tên rõ ràng đó không, một thư mục trong đó tất cả các tệp có định dạng cụ thể hoặc nếu bạn muốn tìm kiếm phân cấp thư mục cho các tên cụ thể và thay đổi các tên này.
Kusalananda

Câu trả lời:


9

Lặp lại tên tệp và sử dụng Mở rộng tham số để chuyển đổi:

for f in *.*.*.txt; do i="${f%.txt}"; echo mv -i -- "$f" "${i//./_}.txt"; done

Mẫu mở rộng tham số, ${f//./_}thay thế tất cả .s bằng _s trong tên tệp ( $f).

Ở trên sẽ thực hiện chạy khô, để cho phép đổi tên thực sự diễn ra, xóa echo:

for f in *.*.*.txt; do i="${f%.txt}"; mv -i -- "$f" "${i//./_}.txt"; done

Nếu bạn muốn đối phó với bất kỳ tiện ích mở rộng nào, không chỉ .txt:

for f in *.*.*.*; do pre="${f%.*}"; suf="${f##*.}"; \
                     echo mv -i -- "$f" "${pre//./_}.${suf}"; done

Sau khi kiểm tra loại bỏ echocho hành động thực tế:

for f in *.*.*.*; do pre="${f%.*}"; suf="${f##*.}"; \
                     mv -i -- "$f" "${pre//./_}.${suf}"; done

Chung, cho số lượng chấm tùy ý, ít nhất một:

for f in *.*; do pre="${f%.*}"; suf="${f##*.}"; \
                 mv -i -- "$f" "${pre//./_}.${suf}"; done

Có một cách chung nếu có một số chấm tùy ý?
Ciprian Tomoiagă

1
@CiprianTomoiaga Do:for f in *.*; do ...; done
heemayl

Tôi có thể đề nghị đưa *.*mẫu thẳng vào ví dụ, vì bây giờ mã có vẻ như chỉ hoạt động với một số chấm cố định.
ilkkachu

@ilkkachu Hội chợ đủ, chỉnh sửa.
heemayl

Cảm ơn bạn rất nhiều heemay, nó đã làm việc cho tôi. và một số học tập!
SG

4

với perltrụ sởrename

$ rename -n 's/\.[^.]+$(*SKIP)(*F)|\./_/g' head.body.date.txt 
rename(head.body.date.txt, head_body_date.txt)
  • \.[^.]+$(*SKIP)(*F) bỏ qua mô hình này và tìm kiếm các trận đấu thay thế
  • |\./_/gthay thế tất cả .bằng_

Hoặc, sử dụng cái nhìn tiêu cực

$ rename -n 's/\.(?![^.]+$)/_/g' head.body.date.txt 
rename(head.body.date.txt, head_body_date.txt)

Một khi điều này là ổn, loại bỏ -ntùy chọn


3
rename 's/\.(?=[^.]*\.)/_/g' *.txt

Sử dụng thay thế regex để tìm tất cả trừ trường hợp cuối cùng .trong tên tệp (giao diện không bắt) và thay thế chúng bằng _. Tổng quát để *.*nếu bạn thích.

(phiên bản đặc biệt này renamedường như được cài đặt qua util-linux). Tôi đang sử dụng Ubuntu 12.04(vâng, hết hạn sử dụng máy).


2

bash:

old=head.body.date.txt oldb=${old%.*} olde=${old##*.} ; \
mv -- "$old" "${oldb//./_}.${olde}"

(1) Bạn nên sử dụng mv --, để bảo vệ chống lại các tên tập tin cũ của bắt đầu -. (2) Bạn nên đặt $olddấu ngoặc kép ( "$old"), để bảo vệ chống lại tên tập tin cũ của cũ có chứa khoảng trắng hoặc ký tự đặc biệt cho trình bao (như *?). (3) Câu trả lời của bạn không thành công trong trường hợp hơi bệnh lý trong đó phần mở rộng chứa dấu gạch dưới: head.body.date.t_xtđược đổi tên thành head_body_date_t.xt.
Scott

@ Hủy, cảm ơn. Mã bây giờ được điều chỉnh theo cả ba mục được đề cập.
agc

1

Sử dụng mv, sedrevtrong một dòng:

mv "head.body.date.txt" "$(echo head.body.date.txt | rev | sed 's/\./_/2g' | rev)"

Nếu bạn muốn áp dụng nó trên tất cả txtcác tệp trong đại diện hiện tại, sử dụng globs có vẻ khó khăn vì cách thức mvhoạt động, nhưng bạn có thể thực hiện một forvòng lặp trong một lớp lót:

for file in *.txt; do mv "$file" "$(echo $file | rev | sed 's/\./_/2g' | rev)"; done

Hơi dài hơn một chút, nhưng bạn có thể phù hợp với một số mẫu trong vòng lặp của bạn!


2
(1) Arrghhh! Đừng làm $(ls …); chỉ cần làm for file in *.txt. (2) Bạn nên sử dụng nhiều trích dẫn : mv "$file" "$(…)".
Scott

Cảm ơn Scott, ghi chú và chỉnh sửa hợp lệ! Tôi vẫn còn là một thanh niên mặc vỏ, xin hãy nhẹ nhàng;)
Valentin B.

Nhìn nhận lại, việc sử dụng renamenhư một số người khác đã gợi ý trong câu trả lời của họ nghe có vẻ đơn giản hơn ...
Valentin B.

-1
 mv head.body.date.txt head_body_date.txt

Nó đơn giản như là cho một tập tin tại một thời điểm. Bạn không xác định liệu bạn muốn điều này được thực hiện đệ quy trong một thư mục hay toàn bộ thư mục, vì vậy đó sẽ là giải pháp nhanh chóng, thuận tiện nhất của bạn.

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.