Làm thế nào để thực hiện thay thế sed tại chỗ chỉ tạo bản sao lưu của các tệp đã được thay đổi?


13

Tôi đã chạy như sau để thay thế một thuật ngữ được sử dụng trong tất cả các tệp trong thư mục làm việc hiện tại:

$ find . -type f -print0 | xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'

Điều này thực hiện thay thế từ nhưng nó cũng tạo ra .bupcác tệp của các tệp không bao giờ có Ms. Johnsonchuỗi.

Làm thế nào để tôi thực hiện thay thế mà không tạo ra tất cả các bản sao lưu không cần thiết này?


đối với tôi như một lỗi của sed thấy
Hotschke

Có lẽ có một cách tiếp cận tốt hơn có thể sử dụng exvà có điều kiện (chỉ khi tệp được thay đổi) chạy :!cp '%' '%.bup'trước khi lưu và thoát. Có thể là giá trị xem xét.
Wildcard

Tôi đã viết một câu hỏi về ý tưởng của tôi ở trên về vitrao đổi ngăn xếp.
tự đại diện

Câu trả lời:


6

Bạn có thể kiểm tra nội dung của tệp để đảm bảo rằng sự thay thế sẽ diễn ra khi sedhoạt động trên chúng:

find . \
    -type f \
    -exec grep -q 'Ms. Johnson' {} \; \
    -print0 |
xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'

Nếu bạn muốn thực sự khéo léo về nó, bạn có thể từ bỏ bằng cách sử dụng findtất cả:

grep -Z -l -r 'Ms. Johnson' |
    xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'

1
Tôi nghĩ rằng bạn cần một '{}'ngay trước khi bạn \;trong đó -exec.
Jander

8

Find có một -exectoán tử thực thi một lệnh tùy ý. Thậm chí tốt hơn, -execlà một thử nghiệm , vì vậy bạn có thể xâu chuỗi nhiều lần -execlại với nhau và nếu các lệnh trước đó thất bại, các lệnh sau sẽ không được thực thi. Chuỗi {}được thay thế bằng tên tệp hiện tại và ;đánh dấu kết thúc lệnh. Bạn nên trích dẫn cả hai để tránh vỏ can thiệp.

Vì thế:

find . -type f \
    -exec grep -q 'Ms. Johnson' '{}' \; \
    -exec sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g' '{}' \;

Tôi chưa bao giờ gặp vấn đề khi sử dụng trần {}.
amphetamachine

1
@amphetamachine: Không có tôi, nhưng trang đàn ông gợi ý điều đó. Nó có thể là một thứ csh, hoặc có thể có shell (không phải Bash và không phải POSIX), người mở rộng {}thành chuỗi null khi thực hiện mở rộng cú đúp.
Jander

4

Tôi nhìn vào trang người đàn ông và không thấy cách nào để làm điều đó trực tiếp sed, vì tôi chắc chắn rằng bạn đã làm trước khi hỏi. Tôi thấy một số cách để khắc phục điều này bằng grep, nhưng tôi nghĩ cách dễ nhất là:

grep -rlZ "Ms. Johnson" . | xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'

-rrecurse
-lin tên tệp chỉ
-Ztên kết thúc với null


-1

Có vẻ như bạn cần xây dựng một danh sách các tệp phù hợp với cụm từ tìm kiếm của bạn trước tiên.

search="test"
for match in $(find -type f -exec grep -l $search "{}" \;)
do sed -i'.bup' -e "/$search/ s/$search/Mrs. Melbin/g" "$match"
done

Bạn quên mất .như là đối số đầu tiên find. Ngoài ra, như tôi đã được thông báo về bản thân cách đây không lâu, bạn thực sự không cần phải trích dẫn hoặc thoát khỏi{}
Kevin

Không tạo danh sách các tệp và thực hiện thay thế lệnh trên đó. Đầu tiên findtạo ra một danh sách các tệp được phân tách bằng dòng mới, sau đó trình bao phá vỡ danh sách này ở bất kỳ khoảng trắng nào (không chỉ dòng mới) và sau đó trình bao xử lý mỗi từ dưới dạng mẫu chung. Điều này chỉ hoạt động nếu tên tệp của bạn không chứa khoảng trắng hoặc \[?*. Các câu trả lời khác trên trang này cho thấy làm thế nào để làm điều này một cách chính xác.
Gilles 'SO- ngừng trở nên xấu xa'

@Kevin Không .cần thiết với find (ít nhất là find find trên linux) bởi vì nó được giả sử khi không có đường dẫn nào được thông qua.
laebshade
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.