Xóa tất cả các tệp trong một thư mục ngoại trừ các tệp X, Y và Z


17

Tôi có rất nhiều tệp thư mục trong một thư mục cụ thể và tôi muốn xóa tất cả chúng; tuy nhiên, tôi muốn giữ các tệp X, Y và Z.

Có cách nào tôi có thể làm một cái gì đó như: rm * | but NOT grep | X or Y or Z


Tôi giả sử tôi có thể sử dụng một số biểu thức chính quy trong đó sẽ làm điều này?
Amit

Câu trả lời:


16

Thay vì sử dụng rm, nó có thể dễ dàng hơn để sử dụng find . Một lệnh như thế này sẽ xóa mọi thứ trừ một tệp có tên chính xác là 'tệp'

find . \! -name 'file' -delete

Nhiều phiên bản nên có thể hỗ trợ kết hợp biểu thức và kết hợp biểu thức chính quy.

Bạn cũng có thể dẫn đầu ra của find đến rm là tốt

find . \! -name '*pattern*' -print0 | xargs --null rm 

3
Và điều này cho phép bạn xem chính xác những tập tin nào sẽ bị xóa bằng cách xóa -deletecũng như những tập tin nào sẽ được lưu bằng cách xóa -delete\!.
Shawn J. Goff

1
cẩn thận, findlà đệ quy! do đó, tất cả các thư mục con không khớp với ' mẫu ' cũng sẽ bị xóa
Alexandre Holden Daly

Cách thông qua xargs cần -depth, để ngăn chặn nỗ lực xóa các thư mục trước khi các tệp có trong chúng. Tuy nhiên, tôi nghĩ rm sẽ không xóa thư mục.
người dùng không xác định

9

Sử dụng zsh, với setopt EXTENDED_GLOB, sử dụng ~toán tử ( ngoại trừ )

rm -- *~(x|y|z)

hoặc ^toán tử (phủ định):

rm -- ^(x|y|z)

Nhưng, có lẽ bạn nên di chuyển các tệp đi nơi khác, sau đó xóa mọi thứ. An toàn hơn nhiều về mặt trượt ngón tay, chẳng hạn như nhấn enter quá sớm.


5

Các phiên bản bash sau này có extglobtùy chọn shell cung cấp cho bạn cú pháp để thực hiện những gì bạn muốn (kiểm tra trang người dùng của bạn trong "Mở rộng tên đường dẫn" để xem phiên bản đã cài đặt của bạn có chưa):

$ shopt -s extglob  # turn on extended globbing
$ rm !(X|Y|Z)

Để kiểm tra, tôi đề nghị đầu tiên bạn thay thế rmvới echođể xem danh sách các file bị xóa là những gì bạn mong đợi.


5
ls -1 | grep -v "^[XYZ]$" # | xargs rm -r

Chú ý: Chạy lệnh và nếu các tệp cần xóa là đúng, hãy chạy lại và xóa ký tự băm "#".

Nếu tên tệp phức tạp hơn thì hãy làm

ls -1 | egrep -v "^file1$|^filename2$|^f1le$" # | xargs rm -r

Một lần nữa, đầu tiên nhìn vào kết quả sau đó loại bỏ dấu băm.

Phiên bản này - như được đề xuất trong các bình luận - lưu một số ký tự và trông rõ ràng hơn một chút.

ls -1 | egrep -v "^(file1|filename2|f1le)$" # | xargs rm -r

Một chỉnh sửa được đề xuất bởi ddeimeke là thay đổi egrepđối số thành"^(file1|filename2|f1le)$"
Michael Mrozek

Nếu bạn có ba tác phẩm a, ba bcác chương trình đầu tiên sẽ xóa - nếu bạn đặt ab vào phần grep: "^[ab]$" abnhưng không a b, chỉ cần trái ngược với ý định của bạn. Lệnh thứ hai sẽ làm tương tự. Và thứ ba cũng vậy. Bạn không nên sử dụng 'ls' trong các tập lệnh, với các ngoại lệ rất, rất hiếm. Đừng làm điều đó.
người dùng không xác định

3

Di chuyển các tập tin bạn muốn tránh xa. Đi lên một cấp, xóa thư mục. Tạo lại thư mục và di chuyển các tập tin đó trở lại.


Tôi tự hỏi tại sao lại là điểm trừ? .. Thật ra cả hai đều dễ dàng và an toàn hơn bất cứ điều gì được đề xuất bởi người khác: bạn chỉ đơn giản là không thể tự bắn vào chân mình bằng cách nhấn một số char đặc biệt trong tên tệp.
alex

a) Bạn di chuyển tệp X của mình lên một thư mục, trong đó tệp X tồn tại - âm thầm bị xóa, biến mất. b) Bạn đang ở vị trí cao nhất, nơi không tồn tại. c) Bạn đang ở của bạn về nhà, và không có quyền ghi vào / home. Nếu bạn đưa lời khuyên của mình vào một kịch bản, và thử nghiệm nó mà không gặp vấn đề gì, và sử dụng nó trong tình huống như vậy - peng!
người dùng không xác định

2
a) Này, tôi đã nói 'di chuyển tập tin lên một cấp' chưa? Tôi đã nói di chuyển chúng đi. b) Vì vậy, bạn đang cố gắng loại bỏ tất cả các tập tin trong /, heh? Không thực tế lắm. c) Cố gắng xóa tất cả các tệp trong của bạn $HOMEcũng không thực tế.
alex

Bạn nói đúng, tôi xin lỗi.
người dùng không xác định

0

Đây là những gì tôi thiết lập dưới dạng tập lệnh .sh cho hook logout OSX / MacOS, hoạt động đủ tốt.

#! /bin/bash
for dir in /PathToFolder/*
 do
    if [ ! "$dir" = "/PathToFolder/FolderToKeep1" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep2" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep3" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep4" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep5" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep6" ] ; then 
      echo ${dir}
      sudo rm -R $dir user
      dscl . -delete $dir
    fi 
  done

exit 0

0

Với GNU-find, bạn có thể sử dụng khóa -delete, loại bỏ các thư mục, nếu trống, quá:

 find tmp -not -name X -not -name Y -not -name Z -delete 

Nếu X, Y hoặc Z là một thư mục, điều này cũng sẽ xóa các tệp bên trong chúng. find tmp -maxdepth 1 -not -name X -not -name Y -not -name Z -deletelà một cách để làm việc này.
Gilles 'SO- ngừng trở nên xấu xa'

Vì các thư mục trong Unix là các tệp (bất cứ thứ gì cũng là một tệp), đó có thể là những gì được dự định. Câu hỏi nói rõ ràng: "Tôi có rất nhiều tệp và thư mục trong một thư mục cụ thể và tôi muốn xóa tất cả chúng;" - và nếu bạn muốn loại trừ Y, có thể bạn biết liệu Y có phải là thư mục hay không.
người dùng không xác định

Điều đó cũng sẽ xóa tmpnếu không có X/ Y/ Ztập tin trong đó. Lưu ý !là tương đương tiêu chuẩn của GNU -not( -deletecũng là phần mở rộng GNU)
Stéphane Chazelas

@ StéphaneChazelas: Từ câu hỏi, xóa các thư mục (tất cả chúng) là những gì được yêu cầu. Vì tiếng nổ cần che, tôi thích gõ -không. Có thể phụ thuộc vào cách bố trí bàn phím tiếng Đức, nơi Backslash cần Alt-Gr.
người dùng không xác định
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.