Làm thế nào để xóa tất cả các tập tin trong một thư mục ngoại trừ một số?


123

Tôi cần xóa tất cả các tập tin trong một thư mục, nhưng loại trừ một số trong số họ. Ví dụ, trong một thư mục chứa các tệp a b c ... z, tôi cần xóa tất cả ngoại trừ up. Có cách nào làm dễ hơn không?


Các câu trả lời dưới đây tốt hơn rất nhiều, nhưng bạn chỉ có thể tạo các tệp để lưu chỉ đọc, xóa tất cả và sau đó thay đổi chúng trở lại quyền ban đầu của chúng (miễn là bạn không sử dụng rm -f). Bạn phải biết những quyền nào để khôi phục và bạn phải biết rằng không cần viết quyền truy cập vào chúng trong quá trình này. Đây là lý do tại sao các câu trả lời khác là tốt hơn.
Joe

1
Nếu bạn cũng muốn xóa các tập tin ẩn chạy shopt -s dotglobtrước khi chạy rm (...).

Câu trả lời:


109

Những gì tôi làm trong những trường hợp đó là gõ

rm *

Sau đó, tôi nhấn Ctrl+ X, *để mở rộng * thành tất cả các tên tệp hiển thị.

Sau đó, tôi có thể loại bỏ hai tệp tôi muốn giữ khỏi danh sách và cuối cùng thực thi dòng lệnh.


25
Tôi đoán điều này chỉ hoạt động miễn là danh sách các tệp *mở rộng quá không quá dài. : -}
Frerich Raabe

9
Esc theo sau * cũng sẽ mở rộng "*".
Slowpoison

2
@SantoshKumar: Điều đó không có ý nghĩa với tôi. Việc mở rộng sẽ luôn hoạt động, nó không phụ thuộc vào lệnh bạn muốn sử dụng sau đó.
Der Hochstapler

2
@OliverSalzburg Xin lỗi, sự kết hợp hơi khó hiểu. Tôi nghĩ bạn nên viết như Ctrl+ Shift+ x+*
Santosh Kumar

2
@SantoshKumar: Nhưng đó không phải là sự kết hợp.
Der Hochstapler

144

Để rmtất cả nhưng u,ptrong bash chỉ cần gõ:

rm !(u|p)

Điều này yêu cầu tùy chọn sau được đặt:

shopt -s extglob

Xem thêm: toàn cầu - Wiki của Greg


1
bạn phải có hoạt động 'extglobbing': shopt -s extglob
sparkie

18
Bạn cần shopt -s extglob, @Ashot. Ngoài ra, đó chỉ là các tệp, không phải thư mục, đó là lý do tại sao tôi đã xóa các -rftùy chọn trong lệnh của bạn.
slhck

3
Nếu bạn cần loại trừ một tệp của một lựa chọn các tệp, hãy thử điều này : rm !(index).html. Thao tác này sẽ xóa tất cả các tệp kết thúc bằng ".html" ngoại trừ "index.html".
mzuther 24/07/2015

71

Bạn có thể dùng find

find . ! -name u ! -name p -maxdepth 1 -type f -delete
  • ! phủ nhận biểu thức tiếp theo
  • -name chỉ định tên tệp
  • -maxdepth 1sẽ làm cho quá trình tìm chỉ thư mục được chỉ định ( findtheo thư mục đi qua mặc định)
  • -type f sẽ chỉ xử lý các tệp (và không phải thư mục ví dụ)
  • -delete sẽ xóa các tập tin

Sau đó, bạn có thể điều chỉnh các điều kiện nhìn vào trang tìm kiếm

Cập nhật

  • Hãy nhớ rằng thứ tự của các thành phần của biểu thức là đáng kể (xem tài liệu)
  • Kiểm tra lệnh của bạn trước bằng cách sử dụng -printthay vì-delete

    find . ! -name u ! -name p -maxdepth 1 -type f -print

5
thứ tự vị ngữ là rất quan trọng ở đây. Nếu một người đặt -deletengay sau .đó sẽ là thảm họa (sẽ xóa tất cả các tệp trong CWD)
Michał rajer

Điều này có thể được viết gọn hơn nhưfind . -maxdepth 1 -type f -name '[^up]' -delete
kojiro

4
@kojiro có nhưng chỉ dành cho các tệp chỉ có một chữ cái. Với những cái tên phức tạp hơn, regex có thể là một mớ hỗn độn.
Matteo

2
findlà người bạn tốt nhất của tôi, đặc biệt là khi có quá nhiều tệp trên toàn cầu
Terence Johnson

43

Đơn giản:

mvcác tập tin bạn muốn trong một thư mục trên, rmthư mục và sau đó mvchúng trở lại.


13
Offcference, mv họ đến một thư mục cao hơn. Cố gắng không chuyển chúng đến thư mục con mà bạn đang xóa ...
Konerak

@Konerak: rmkhông -rsẽ không loại bỏ các thư mục con.
rebierpost

11
Điều này sẽ ghi đè lên các tệp có cùng tên trong thư mục đích
Matteo

7
Tôi đang hạ thấp điều này bởi vì trong khi nó có thể có ích, nó cũng không phải là nguyên tử và loại bỏ hiệu quả tất cả các tệp khỏi thư mục trong một khoảng thời gian ngắn; điều này sẽ không được chấp nhận nếu, ví dụ, các tệp đang được chia sẻ trên mạng.
sam hocevar

15

Khá giống với câu trả lời này nhưng không có tùy chọn đặc biệt nào là cần thiết, theo như tôi biết sau đây là chức năng "cổ đại" được hỗ trợ bởi bất kỳ vỏ (mơ hồ) / bin / sh nào (ví dụ bash, zsh, ksh, v.v.)

rm [^up]

2
Điều này làm việc cho tên tập tin 1-char. Đối với tên dài hơn, câu trả lời của Sparkie là tốt hơn.
glenn jackman

3
Điều gì sẽ xảy ra với rm [^up]*? Tôi làm những điều tương tự khá thường xuyên.
một CVn

3
@ MichaelKjorling - điều này sẽ xóa tất cả các tệp bắt đầu bằng u hoặc p, không chỉ những tệp có tên u và p. Tôi nghĩ OP (@Ashot) có nghĩa là az và u, p, v.v. tượng trưng và không theo nghĩa đen.
Sudipta Chatterjee

4
@HobbesofCalvin Điều đó sẽ xóa tất cả các tệp không bắt đầu bằng u hoặc p, không phải những tệp bắt đầu với chúng.
rjmunro

@rjmunro - cảm ơn, đã bỏ lỡ cái đó! :)
Sudipta Chatterjee

11

Làm điều đó mà không tìm thấy:

ls | grep -v '(u|p)' | xargs rm

(Chỉnh sửa: "u" và "v", như ở những nơi khác ở đây, đang được sử dụng làm phiên bản chung của toàn bộ các biểu thức. Rõ ràng bạn sẽ muốn cẩn thận neo các biểu thức của mình để tránh khớp quá nhiều thứ.)

Bạn chắc chắn sẽ muốn có một kịch bản nếu bạn sẽ thực hiện nhiều điều này, như những người khác đã đề xuất.


grep sẽ không xử lý regexpt mở rộng theo mặc định: sử dụng -Ehoặcegrep
Matteo

2
điều này sẽ loại trừ bất kỳ tệp nào chứa một uhoặc mộtp
Matteo

@Matteo Không, nó sẽ không. Grep không grepping các tập tin, nó grepping đầu ra của lệnh ls. Bạn đang nghĩ về một cái gì đó giống như grep -L (u|p)' * | xargs rmnơi -Ldanh sách tên tệp không chứa một trận đấu.
rjmunro

4
Ồ, ý bạn là bất kỳ tập tin nào tên người chứa uhoặc p, không phải bất kỳ tập tin nào chứa a uhoặc a p. Đúng rồi. Bạn có thể khắc phục bằng cách sử dụngegrep -v '^(u|p)$'
rjmunro

1
Đây là loại bỏ tất cả mọi thứ trừ những trận đấu! ls | grep -v 'vuze\|progs' | xargs rm -rf
Nick

6

Trong zsh:

setopt extended_glob  # probably in your .zshrc

sau đó

rm ^(u|p)

hoặc là

rm *~(u|p)

Thứ hai sẽ làm việc ngay cả khi bạn có ^trong $histcharssử dụng quyền thay lịch sử, và tất nhiên bạn có thể đặt một glob tùy ý trước ~.


5

GLOBIGNORE có một danh sách được phân tách bằng dấu hai chấm

GLOBIGNORE=u:p
rm *

12
Điều này không hoạt động trên shell của tôi (GNU bash 4.1.5 (1)). Hãy chắc chắn kiểm tra nó trước với một cái gì đó ít gây hại hơnrm hoặc trong một thư mục thử nghiệm!
một CVn

3

Quay trở lại thời kỳ mềm, tôi đã có một chương trình thực thi dos gọi là "Ngoại trừ" sẽ di chuyển mọi thứ ra khỏi thư mục hiện tại theo thời gian và thực thi một lệnh, vì vậy bạn có thể nói:

ngoại trừ * .txt del *. *

để xóa tất cả mọi thứ trừ các tập tin văn bản của bạn.

Đây sẽ là một điều khá nhỏ để thực hiện như một kịch bản shell và nếu đây là loại việc bạn có khả năng làm nhiều hơn hai lần thì có vẻ như đó sẽ là một ý tưởng tốt.


2
Nó nhắc tôi điều tương tự. Nhưng tạm thời chuyển ra khỏi thư mục có thể không phải là một ý tưởng hay trong thời đại đa nhiệm :)
Sedat Kapanoglu

3
 find . -maxdepth 1 ! -name "u" ! -name "p" -type f -exec rm -rf {} \;

Điều này sẽ xóa tất cả các tệp ngoại trừ u và p trong unix


2

Đối với những người thích chỉ định các mẫu loại trừ phức tạp tùy ý (bao trùm tất cả các tên tệp bị ảnh hưởng) theo kiểu emacs regrec đầy đủ, kiểu posix-awk hoặc kiểu mở rộng posix (xem trang man) tôi sẽ đề xuất kiểu này. Nó loại trừ uptrong thư mục hiện tại trong ví dụ này. Điều này có thể hữu ích cho các kịch bản.

find -regextype posix-awk ! -regex './(u|p)' -print0 | xargs -0 rm -rf

Bạn cần chỉ định một thư mục trước biểu thức (`find. -Regextype ...).
Matteo

-regextypesẽ chỉ hoạt động trên các phiên bản GNU
Matteo

không - phiên bản tìm kiếm của tôi (debian bóp) chắc chắn không yêu cầu một thư mục rõ ràng trước biểu thức nếu thư mục hiện tại nên được sử dụng
sparkie

@sparke: điều này chỉ hoạt động trên các triển khai GNU
Matteo

@sparkie: không xác định thư mục (tham số đầu tiên) cho findlà phần mở rộng của findlệnh GNU . Áp dụng tương tự cho -regextypetùy chọn. Ngoài ra, lệnh của bạn cũng sẽ xóa các tệp trong thư mục con, trong khi câu hỏi ban đầu hỏi rõ ràng về các tệp trong một thư mục.
Mikko Rantalainen

1

Tôi luôn luôn sử dụng:

rm [a-o,q-t,v-z]*

Điều này sẽ cho phép bạn xác định mức độ chi tiết mà bạn muốn thực hiện. Vì vậy, nếu bạn muốn xóa các tập tin o và Z, bạn có thể sử dụng:

rm [a-o,z]*

1

Một phiên bản khác sử dụng xargs:

ls -1 | grep -v do_not_delete | xargs -I files rm "files"

Lưu ý rằng xargs -Icần thiết để xử lý tên tệp bao gồm cả khoảng trắng một cách chính xác.


1

Còn nữa:

for FILE in ./*; do if [[ $FILE != ./u* ]] || [[ $FILE != ./p* ]];then rm $FILE; fi; done;

Nó khá dài và tôi không biết liệu bạn có thể dễ dàng biến nó thành một hàm có thể dễ dàng chứa và số lượng đối số tùy ý hay không, nhưng nó hoạt động tốt.

đó là lòng tốt bash thuần túy.


1

Đây là một biến thể khác. Bạn có thể gõ:

rm -i *

hoặc là:

rm --interactive *

Vì vậy, rmsẽ yêu cầu bạn xác nhận xóa từng tập tin.


1

Sử dụng:

find . -type f ! -name 'u' ! -name 'p' ! -name '*.ext' -delete
find . -type d ! -name 'u' ! -name 'p' ! -name '*.ext' -delete

để xóa tất cả các tệp bao gồm các thư mục, ngoại trừ các tệp u, p và .ext.


0

Một cách đơn giản khó gây rối: giả sử bạn muốn xóa mọi thứ trừ * .pdf:

mkdir tmp
mv *.pdf tmp
rm *
mv tmp/* .
rm -r tmp
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.