Linux: удаление файлов, которые не содержат все указанные слова - PullRequest
11 голосов
/ 05 марта 2009

Внутри каталога, как я могу удалить файлы, в которых отсутствует любое из указанных слов, чтобы остались только файлы, содержащие ВСЕ слова? Я пытался написать простой скрипт оболочки bash, используя команды grep и rm, но я заблудился. Я совершенно новичок в Linux, любая помощь будет оценена

Ответы [ 8 ]

20 голосов
/ 05 марта 2009

Как насчет:

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

Если файл не содержит foo, то первая строка удалит его.

Если файл не содержит bar, то вторая строка удалит его.

Должны быть оставлены только файлы, содержащие foo и bar

-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.

См. Также @ пост Николая Голубева для размещения в петле.

11 голосов
/ 05 марта 2009
list=`Word1 Word2 Word3 Word4 Word5`
for word in $list
    grep -L $word *.txt | xargs rm
done
5 голосов
/ 05 марта 2009

Дополнение к ответам выше: используйте символ новой строки в качестве разделителя для обработки имен файлов с пробелами!

grep -L $word $file | xargs -d '\n' rm
1 голос
/ 05 марта 2009

Чтобы сделать те же самые имена файлов (а не содержимое файлов, как в большинстве решений выше), вы можете использовать следующее:

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

Согласно комментариям:

for file in `ls`

не должен использоваться. Ниже делает то же самое без использования ls

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

-ve отменяет поиск шаблона регулярного выражения для foo или bar в имени файла. Любые дальнейшие слова, которые будут добавлены в список, должны быть разделены \ | например один \ | два \ | три

1 голос
/ 05 марта 2009

grep -L слово | xargs rm

0 голосов
/ 05 марта 2009

Вы можете попробовать что-то вроде этого, но это может сломаться если шаблоны содержат shell или grep метасимволы:

(в этом примере один-два-три - это шаблоны)

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 
0 голосов
/ 05 марта 2009

При этом будут удалены все файлы, которые не содержат слов Пинг или Отправлено

grep -L 'Ping\|Sent' * | xargs rm
0 голосов
/ 05 марта 2009

Сначала удалите список файлов:

rm flist

Затем для каждого слова добавьте файл в список файлов, если он содержит это слово:

grep -l WORD * >>flist

Затем сортируйте, унифицируйте и получайте счет:

sort flist | uniq -c >flist_with_count

Все те файлы в flsit_with_count, у которых нет количества слов, должны быть удалены. Формат будет:

2 file1
7 file2
8 file3
8 file4

Если было 8 слов, то файл1 и файл2 должны быть удалены. Я оставлю написание / тестирование сценария вам.

Хорошо, вы меня убедили, вот мой сценарий:

#!/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} {}')

При этом удаляются файлы в каталоге, в котором не было всех трех слов:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...