2009-03-05 24 views
11

Dentro de un directorio, ¿cómo puedo eliminar archivos que carecen de alguna de las palabras especificadas, de modo que solo queden los archivos que contienen TODAS las palabras? Traté de escribir un script simple de bash shell usando los comandos grep y rm, pero me perdí. Estoy totalmente nuevo en Linux, cualquier ayuda se agradeceLinux: eliminando archivos que no contienen todas las palabras especificadas

Respuesta

20

Cómo sobre: ​​

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

Si un archivo no contiene no contiene foo, entonces la primera línea eliminará ve eso

Si un archivo no contienen bar, a continuación, la segunda línea se eliminará.

Sólo los archivos que contienen tanto foo y bar deben dejarse

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

Véase también @Mykola Golubyev's post para colocar en un bucle.

+0

creo que los archivos con foo O bar, se eliminarán con esto. – claf

+0

Nope - -L niega el grep. – toolkit

+0

@toolkit: oups, mi mal. – claf

0

En primer lugar, eliminar la lista de archivos:

rm flist 

Entonces, para cada una de las palabras, añadir el archivo a la lista de archivos si contiene esa palabra :

grep -l WORD * >>flist 

Entonces especie, uniqify y obtener un recuento:

sort flist | uniq -c >flist_with_count 

Todos esos archivos en FLSI t_with_count que no tiene el número de palabras debe ser eliminado. El formato será:

2 file1 
7 file2 
8 file3 
8 file4 

Si hubo 8 palabras, se deben eliminar el archivo1 y el archivo2. Dejaré la escritura/prueba del guión para usted.

Vale, me has convencido, aquí está mi guión:

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

Esto elimina los archivos en el directorio que no tenían las tres palabras:

-2

Esto eliminará todos los archivos que no contiene palabras de ping o enviados

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

Esto no eliminará los archivos que solo contengan una de las Palabras. –

+0

Sí, ya lo he notado y presiono eliminar, pero ya era demasiado tarde. –

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

adición a las respuestas anteriores: Utilice el carácter de nueva línea como delimitador de manejar nombres de archivo con espacios !

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

Para ello los mismos nombres de archivo coincidentes (no el contenido de los archivos ya que la mayoría de las soluciones arriba) se puede utilizar lo siguiente:

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

De acuerdo con los comentarios:

for file in `ls` 

shouldn no ser usado El siguiente hace lo mismo sin utilizar el ls

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

la -ve invierte el patrón de búsqueda de la expresión regular, ya sea para foo o bar en el nombre del archivo. Cualquier otra palabra que se agregue a la lista debe estar separada por \ | p. uno \ | dos \ | tres

+0

Para el archivo en 'ls' es una mala idea. – porges

+0

Buen punto. Editado en consecuencia, pero no me gusta cómo eso lo complica. ¿Puedes pensar en una manera más eficiente? – Andy

0

Usted podría intentar algo como esto, pero puede romper si los patrones contienen cáscara o grep meta caracteres:

(en este ejemplo uno dos tres son los patrones)

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 
Cuestiones relacionadas