2009-03-05 23 views
11

Bên trong một thư mục, làm cách nào để xóa các tệp thiếu bất kỳ từ nào được chỉ định để chỉ các tệp chứa TẤT CẢ các từ còn lại? Tôi đã cố gắng để viết một kịch bản shell bash đơn giản bằng cách sử dụng lệnh grep và rm, nhưng tôi đã bị mất. Tôi hoàn toàn mới sang Linux, bất kỳ trợ giúp sẽ được đánh giá caoLinux: Xóa các tệp không chứa tất cả các từ được chỉ định

Trả lời

20

Làm thế nào về:

grep -L foo *.txt | xargs rm 
grep -L bar *.txt | xargs rm 

Nếu tệp có không chứa foo, thì dòng đầu tiên sẽ được làm lại ve nó.

Nếu một tập tin không không chứa bar, sau đó dòng thứ hai sẽ loại bỏ nó.

Chỉ những tập tin có chứa cả foobar nên để

-L, --files-without-match 
    Suppress normal output; instead print the name of each input 
    file from which no output would normally have been printed. The 
    scanning will stop on the first match. 

Xem thêm @Mykola Golubyev's post để đặt trong một vòng lặp.

+0

tôi nghĩ rằng các tệp có foo OR bar, sẽ bị xóa với điều này. – claf

+0

Không - -L phủ nhận grep. – toolkit

+0

@toolkit: oups, xấu của tôi. – claf

0

Thứ nhất, loại bỏ các filelist:

rm flist 

Sau đó, đối với mỗi người trong số các từ, thêm các tập tin vào filelist nếu nó có chứa từ đó :

grep -l WORD * >>flist 

Sau đó sắp xếp, uniqify và có được một số lượng:

sort flist | uniq -c >flist_with_count 

Tất cả các tập tin trong flsi t_with_count không có số từ cần xóa. Định dạng sẽ là:

2 file1 
7 file2 
8 file3 
8 file4 

Nếu có 8 từ, thì tệp1 và tệp2 sẽ bị xóa. Tôi sẽ để lại văn bản/thử nghiệm của kịch bản cho bạn.

Được rồi, bạn đã thuyết phục tôi, đây là kịch bản của tôi:

#!/bin/bash 
rm -rf flist 
for word in fopen fclose main ; do 
    grep -l ${word} *.c >>flist 
done 
rm $(sort flist | uniq -c | awk '$1 != 3 {print $2} {}') 

này loại bỏ các tập tin trong thư mục đó không có tất cả ba chữ:

-2

này sẽ loại bỏ tất cả các file mà không chứa các từ Ping hoặc Sent

grep -L 'Ping\|Sent' * | xargs rm 
+0

Thao tác này sẽ không xóa các tệp chỉ chứa một trong các Từ. –

+0

Có, tôi đã nhận thấy rằng đã và nhấn xóa, nhưng đã quá muộn. –

11
list=`Word1 Word2 Word3 Word4 Word5` 
for word in $list 
    grep -L $word *.txt | xargs rm 
done 
5

bổ sung các câu trả lời ở trên: Sử dụng các ký tự xuống dòng như delimiter để xử lý tên tập tin với không gian !

grep -L $word $file | xargs -d '\n' rm 
1

Để làm tên tập tin khớp cùng (không phải là nội dung của các file như hầu hết các giải pháp nêu trên), bạn có thể sử dụng như sau:

for file in `ls --color=never | grep -ve "\(foo\|bar\)"` 
do 
    rm $file 
done 

Theo nhận xét:

for file in `ls` 

shouldn không được sử dụng. Dưới đây làm điều tương tự mà không sử dụng ls

for file in * 
do 
    if [ x`echo $file | grep -ve "\(test1\|test3\)"` == x ]; then 
    rm $file 
    fi 
done 

các -ve đảo ngược việc tìm kiếm các mô hình regexp cho một trong hai foo hoặc thanh trong tên tập tin. Bất kỳ từ nào khác cần thêm vào danh sách cần được phân tách bằng \ | ví dụ: một \ | hai \ | ba

+0

Đối với tệp trong 'ls' là một ý tưởng tồi. – porges

+0

Điểm tốt. Chỉnh sửa cho phù hợp, nhưng tôi không thích làm thế nào mà nó phức tạp. Bạn có thể nghĩ ra một cách hiệu quả hơn không? – Andy

0

Bạn có thể thử một cái gì đó như thế này nhưng nó có thể phá vỡ nếu mẫu chứa vỏ hoặc grep ký tự meta:

(trong ví dụ này một hai ba là các mẫu)

for f in *; do 
    unset cmd 
    for p in one two three; do 
    cmd="fgrep \"$p\" \"$f\" && $cmd" 
    done 
    eval "$cmd" >/dev/null || rm "$f" 
done 
Các vấn đề liên quan