Loại trừ một mẫu khỏi trận đấu toàn cầu


54

Tôi có một số tệp có cùng tên tệp cơ sở. Tôi muốn xóa tất cả trừ một

foo.org #keep
foo.tex #delete
foo.fls #delete
foo.bib #delete
etc

Nếu tôi không cần giữ một cái, tôi biết tôi có thể sử dụng rm foo.*.

TLDP thể hiện ^để phủ nhận một trận đấu. Thông qua thử nghiệm và lỗi, tôi đã có thể tìm thấy rằng

rm foo.*[^org]

làm những gì tôi cần, nhưng tôi không thực sự hiểu cú pháp.

Ngoài ra, mặc dù không phải là một giới hạn trong trường hợp sử dụng của tôi, tôi nghĩ rằng mô hình này cũng bỏ qua foo.ofoo.or. Làm thế nào để mô hình này hoạt động, và một quả cầu mà bỏ qua chỉ foo.org trông như thế nào?


1
Ngoài việc trả lời @glen, điều đáng nói là rm foo.*[^org]loại bỏ tất cả các tệp mà ký tự cuối cùng không phải o, rhoặc g, do đó, foo.foocũng không khớp.
jimmij

Bạn đang sử dụng a Regular Expression. Bạn nên cẩn thận với các nhân vật nhóm của bạn. Bằng cách sử dụng dấu ngoặc bạn đã chỉ định một ý nghĩa lớp nhân vật mà bạn sẽ xóa bất kỳ tập tin đó có một phần mở rộng với các chữ cái o, rhoặc gtrong bất kỳ thứ tự. Sử dụng dấu ngoặc đơn để tạo một nhóm và giữ nguyên thứ tự các ký tự.
Ông Mascaro

3
@ jbarker2160 - đó không thực sự là một biểu thức chính quy, nó thường được gọi là toàn cầu (hoặc mẫu tên tệp ), ít nhiều là một tập hợp con của biểu thức chính quy - xem phần khớp mẫu của trang bash để biết chi tiết. Mẫu của anh ta foo.*[^org]sẽ khớp với bất kỳ tên tệp nào bắt đầu bằng foo.một hoặc nhiều ký tự sau dấu chấm trong đó ký tự cuối cùng không phải là o, r hoặc g. Vì vậy, nó sẽ phù hợp foo.orb, nhưng không foo.orghay foo.orhay foo.o. Câu trả lời của GlennJackman cho thấy cách bật các tính năng khớp mẫu mở rộng để phủ định kết quả khớp.
Johnny

Câu trả lời:


52
shopt -s extglob
echo rm foo.!(org)

Đây là "foo." tiếp theo là bất cứ điều gì KHÔNG "org"

ref: https://www.gnu.org/software/bash/manual/bashref.html#Potype-Matching


Tôi đã thử làm tương tự nhưng với dấu ngoặc và rõ ràng khi sử dụng dấu ngoặc thì nó không hoạt động
Donato

4
Cú pháp để khớp nhiều tên tập tin là gì? nói rằng tôi muốn loại trừ .org, .png, .txt?
Freedo

@Freedo @()cho danh sách mẫu: stackoverflow.com/a/217208/3779853
phil294

23

Trong bash, bạn cũng có thể sử dụng GLOBIGNORE="*.org"; rm -i foo*.

unset GLOBIGNOREkhi hoàn thành.

Nó không thực sự tốt hơn shopt -s extglob, nhưng tôi thấy dễ nhớ hơn.


5
@Ruslan Điều đó không hiệu quả. Bạn nên làm( GLOBIGNORE="*.org"; rm -i foo* )
DBedrenko

3
Lưu ý nếu bạn muốn mở rộng danh sách bị bỏ qua, tách biệt bằng dấu hai chấm, chẳng hạn nhưGLOBIGNORE="*foo*:*bar*"
phyatt

7

Một đường ống có thể làm gì?

ls * | grep -v "foo.org" | xargs -I {} echo {}

(rõ ràng bạn có thể muốn thay thế echo bằng rm trong chuỗi cuối cùng).


Hữu ích nếu cần chỉ trong một dòng.
bruceskyaus

1
Dễ nhớ hơn (đối với tôi, tôi thường xuyên làm điều đó) và cho phép xử lý phức tạp hơn để khởi động :)
drevicko

1
ls -1đáng tin cậy hơn để đảm bảo tất cả các tệp được xử lý grepriêng
MichaelChirico

0

OP đã rất gần:

rm foo.*[^o][^r][^g]

mặc dù trong trường hợp *này là không cần thiết

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.