All'interno di una directory, come posso eliminare i file che non contengono le parole specificate, in modo che siano rimasti solo i file che contengono TUTTE le parole? Ho provato a scrivere un semplice script di shell bash usando i comandi grep e rm, ma mi sono perso. Sono totalmente nuovo per Linux, tutto l'aiuto sarebbe apprezzatoLinux: rimozione di file che non contengono tutte le parole specificate
risposta
Come su:
grep -L foo *.txt | xargs rm
grep -L bar *.txt | xargs rm
Se un file è non contiene foo
, quindi la prima riga verrà rimossa ve.
Se un file non non contengono bar
, poi la seconda linea sarà rimuoverlo.
solo i file che contengono sia foo
e bar
dovrebbero essere lasciati
-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.
Vedi anche @Mykola Golubyev's post per l'immissione in un ciclo.
In primo luogo, rimuovere il filelist:
rm flist
Poi, per ciascuna delle parole, aggiungere il file al filelist se contiene quella parola :
grep -l WORD * >>flist
quindi ordinare, uniqify e ottenere un conteggio:
sort flist | uniq -c >flist_with_count
tutti quei file in flsi t_with_count che non ha il numero di parole dovrebbe essere cancellato. Il formato sarà:
2 file1
7 file2
8 file3
8 file4
Se c'erano 8 parole, quindi file1 e file2 devono essere eliminati. Lascerò la scrittura/test della sceneggiatura a te.
Ok, mi hai convinto, ecco il mio script:
#!/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} {}')
Questo rimuove i file nella directory che non hanno tutte le tre parole:
Questo consente di eliminare tutti i file che non contenga parole Ping o inviati
grep -L 'Ping\|Sent' * | xargs rm
Ciò non rimuoverà i file che contengono solo una delle parole. –
Sì, l'ho già notato e ho premuto delete, ma era troppo tardi. –
list=`Word1 Word2 Word3 Word4 Word5`
for word in $list
grep -L $word *.txt | xargs rm
done
aggiunta alle risposte di cui sopra: utilizzare il carattere di nuova riga come delimitatore di gestire i nomi di file con spazi !
grep -L $word $file | xargs -d '\n' rm
grep -L parola | xargs rm
a fare lo stesso nome di file corrispondenti (non il contenuto dei file come la maggior parte delle soluzioni di cui sopra) è possibile utilizzare il seguente:
for file in `ls --color=never | grep -ve "\(foo\|bar\)"`
do
rm $file
done
Come per i commenti:
for file in `ls`
shouldn essere usato Il sotto fa la stessa cosa senza utilizzare il ls
for file in *
do
if [ x`echo $file | grep -ve "\(test1\|test3\)"` == x ]; then
rm $file
fi
done
La ve inverte la ricerca del modello regexp sia per foo o la barra nel nome del file. Eventuali ulteriori parole da aggiungere all'elenco devono essere separate da \ | ad es. uno \ | due \ | tre
Si potrebbe provare qualcosa di simile, ma si può rompere se i modelli contengono guscio o grep meta caratteri:
(in questo esempio uno due tre sono i modelli)
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
penso che i file con foo OR bar, verranno eliminati con questo. – claf
No - L nega il grep. – toolkit
@toolkit: oups, my bad. – claf