Xóa tất cả các tệp / thư mục ngoại trừ một tệp


244

Tôi có một thư mục chứa một số lượng lớn các tập tin. Tôi muốn xóa tất cả các tập tin ngoại trừ file.txt. Làm thế nào để tôi làm điều này?

Có quá nhiều tệp để loại bỏ những cái không mong muốn riêng lẻ và tên của chúng quá đa dạng để sử dụng * để xóa tất cả chúng ngoại trừ một tệp này.

Có người đề nghị sử dụng

rm !(file.txt)

Nhưng nó không hoạt động. Nó trở lại:

Badly placed ()'s 

Hệ điều hành của tôi là Khoa học Linux 6.

Có ý kiến ​​gì không?


13
di chuyển cái bạn muốn giữ, sau đó rm những người khác?
Olivier Dulac

5
@OlivierDulac Có phải chúng tôi là hai người duy nhất trong câu hỏi này không suy nghĩ quá nhiều về câu hỏi?
Shadur

1
@shadur: tốt, tôi có thể liên quan đến họ: oneliners rất hấp dẫn ... ^^
Olivier Dulac

1
Cảm ơn, và vâng tôi đang tìm kiếm một giải pháp một dòng. Quá tốn thời gian để tiếp tục di chuyển các tệp vì tôi phải làm việc này khá thường xuyên.
Kantura

Câu trả lời:


288

POSIXly:

find . ! -name 'file.txt' -type f -exec rm -f {} +

sẽ xóa tất cả các tệp thông thường (đệ quy, kể cả các tệp ẩn) ngoại trừ file.txt. Để loại bỏ các thư mục, thay đổi -type fđể -type dvà thêm -rtùy chọn để rm.

Trong bash, để sử dụng rm -- !(file.txt), bạn phải kích hoạt extglob :

$ shopt -s extglob 
$ rm -- !(file.txt)

(hoặc gọi bash -O extglob)

Lưu ý rằng extglobchỉ hoạt động trong bashvà vỏ Korn. Và sử dụng rm -- !(file.txt)có thể gây ra Argument list too longlỗi.

Trong zsh, bạn có thể sử dụng ^để phủ định mẫu có bật tính năng mở rộng :

$ setopt extendedglob
$ rm -- ^file.txt

hoặc sử dụng cùng một cú pháp với kshbashvới các tùy chọn ksh_globno_bare_glob_qualđược bật.


9
Chỉ định thư mục là thông lệ tốt (fullpath trong trường hợp này? Hoặc có thể thêm cảnh báo ở đây rằng lệnh này sẽ xóa mọi tệp bắt đầu từ thư mục làm việc hiện tại ?). Tôi cũng thường viết bất kỳ ví dụ với rmnhư echo rmthay vào đó, và yêu cầu mọi người chỉ đưa ra tiếng vang khi họ thực sự chắc chắn nó sẽ làm những gì họ muốn. Ngoài ra, +1 cho câu trả lời thấu đáo
Olivier Dulac

11
Tôi muốn đề nghị -deletethay vì -exec, ngắn hơn và dễ nhớ hơn
Izkata

6
@Izkata: -deletekhông được xác định bởi POSIX.
cuonglm

5
Làm thế nào để loại trừ danh sách các tập tin?
Meysam

5
@Meysam - xem câu trả lời của tôi cho một giải pháp sẽ xử lý danh sách các tệp. Khác với findgiải pháp của Gnouc bạn có thể làm ! \( -name one_file -o -name two_file \)và cứ thế.
mikeerv

112

Một hướng đi khác theo một hướng khác (nếu không có khoảng trắng trong tên tệp)

ls | grep -v file.txt | xargs rm

hoặc (hoạt động ngay cả khi có khoảng trắng trong tên tệp)

ls | grep -v file.txt | parallel rm

từ man grep:

 -v, --invert-match
          Invert the sense of matching, to select non-matching lines.  (-v is specified by POSIX)

2
Nó sẽ không hoạt động nếu tên tệp có khoảng trắng ...
Matteo

1
Ciao @Matteo, nó hoạt động cho các tập tin với không gian quá, nhưng bạn cần phải bao quanh grep-pattern bởi dấu ngoặc kép, ví dụ ls | grep -v "a file with spaces.bin" | xargs rm. Đây là grepcú pháp bình thường .
Sebastian

1
@Sebastian Vấn đề không phải là grepnhưng rm. rmsẽ nhận được một danh sách các đối số được phân tách không gian. Hãy thử touch 'a b'; touch 'c d'; ls | grep -v 'a b' | xargs rm: bạn sẽ nhận được rm: c: No such file or directoryrm: d: No such file or directory
Matteo

1
Vâng, đây là một vấn đề phổ biến. Xem các tùy chọn -print0trong find-0trong xargs. Đây là một cách giải quyết, nhưng hơi bất tiện. find . -maxdepth 1 -type f | grep -v 'a b' | tr '\n' '\0' | xargs -0 rm. Nhân tiện, gnu parallelxử lý việc này rất tốt (tôi hầu như luôn sử dụng nó để thay thế cho xargs:ls | grep -v 'a b' | parallel rm
Sebastian

1
Đó không chỉ là khoảng trắng, tất cả đều là khoảng trắng và dòng mới, mà còn trích dẫn các ký tự (dấu ngoặc đơn, dấu ngoặc kép và dấu gạch chéo ngược) và tên tệp bắt đầu bằng -.
Stéphane Chazelas

32

Duy trì một bản sao, xóa mọi thứ, khôi phục bản sao:

{   rm -rf *
    tar -x
} <<TAR
$(tar -c $one_file)
TAR

Trong một dòng:

{ rm -rf *; tar -x; } <<< $(tar -c $one_file)

Nhưng điều đó đòi hỏi một vỏ hỗ trợ ở đây - chuỗi.


10
Điều này là hơi khó chịu.
vschum

2
@Derek - vui lòng xem chỉnh sửa.
mikeerv

2
Nhưng nếu điều này bị gián đoạn giữa chừng, hoặc nếu có gì sai, tập tin sẽ biến mất.
kasperd

2
@kasperd - không. Chỉ khi vỏ cha chết giữa thời gian nó chạy rmtar -x. rmcó thể thất bại nhiều như nó muốn.
mikeerv

2
Không hiệu quả hơn để di chuyển nó sang thư mục khác và di chuyển nó trở lại? Chúng ta không cần phải xử lý nội dung của tệp, chỉ với đường dẫn của nó.
leonbloy

23

tất cả các bạn đều đánh giá cao điều này.

cd ..
mv fulldir/file.txt /tmp/
rm -rf fulldir
mkdir fulldir
mv /tmp/file.txt fulldir/

Làm xong.

EDIT Trên thực tế, dễ dàng hơn:

cd ..
ln fulldir/file.txt ./
rm -rf fulldir
mkdir -p fulldir
mv file.txt fulldir/

3
đó là điều tương tự câu trả lời của tôi. exce [pt nó không mất bất kỳ quyền nào trên thư mục.
mikeerv

6
Nếu đó là một tệp lớn trên một hệ thống tệp riêng biệt từ / tmp và bạn đang cố xóa mọi thứ khỏi thư mục gốc của hệ thống tệp, thì việc di chuyển nó đến nơi an toàn có thể không phải là một tùy chọn.
Johnny

1
Đây chắc chắn là câu trả lời đơn giản nhất.
Ben Liyanage

17

Trên HĐH Linux Linux 6 của tôi, nó hoạt động:

shopt -s extglob
rm !(file.txt)

Tôi cũng đã cài đặt Debian 32bit trên Máy ảo. Ở trên không hoạt động nhưng sau đây không:

find . -type f ! -name 'file.txt' -delete

1
Ý bạn là findgiải pháp tôi đưa ra không hiệu quả?
cuonglm

"Không hoạt động" hoặc "không hoạt động". Có giải pháp tìm của bạn cũng hoạt động. Cảm ơn.
Kantura

1
Bạn có thể làm cho nó chi tiết hơn? Làm thế nào "không hoạt động? Nó không xóa các tập tin khác, hoặc nó đã xóa file.txthoặc bất cứ điều gì khác?
cuonglm

Ý tôi là trên hệ điều hành Debian "$ rm! (File.txt)" trả về "Badly put () 's". Vì vậy, tôi đã thử "$ shopt -s extglob", nhưng nó đã trả về: "shopt: Lệnh không tìm thấy". Sau đó, tôi đã thử giải pháp "tìm". Nó làm việc
Kantura

1
Ồ, vậy dĩ nhiên là nó không hoạt động. shoptkhông phải là tcshnội dung.
cuonglm

10

Sử dụng rm !("file.txt")thay vìrm !(file.txt)


4
Điều đó làm cho hoàn toàn không có sự khác biệt nào. Vấn đề ở đây là OP là 1) không sử dụng shell hỗ trợ định dạng này và 2) ngay cả trong bash, bạn cần kích hoạt nó với shopt -s extglob. Trong mọi trường hợp, trích dẫn một tên tệp đơn giản như thế sẽ không có sự khác biệt.
terdon

1
Để giữ thư mục utils làm - rm -rf! ("
Utils

7

Chỉ cần đưa ra một câu trả lời khác, bạn có thể sử dụng hành vi mặc định rmrằng nó sẽ không xóa các thư mục:

mkdir tmp && mv file.txt tmp  # create tmp dir and move files there
rm                            # delete all other files
mv tmp/* . && rm -rf tmp      # move all files back and delete tmp dir

1

Tôi thấy rằng phương pháp này rất đơn giản, hiệu quả và không yêu cầu bất kỳ tiện ích mở rộng đặc biệt nào (mà tôi biết!)

ls --hide=file.txt | xargs rm
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.