Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

grep qui renvoie le nom du fichier uniquement

18 réponses
Avatar
Kevin Denis
Bonjour,

je dois trier un très grand nombre de fichiers qui contiennent une
ou plusieurs fois une pattern.

Je fais donc un grep, suivi d'un sort -u pour avoir une fois
uniquement les fichiers.
Est il possible avec grep de donner le nom du fichier une seule fois?

La commande est:
find directory/ -type f -exec grep "pattern" {} \; -print > /tmp/liste

Est il possible de n'avoir que le nom des fichiers comportant
pattern d'une manière plus élégante?
Merci
--
Kevin

10 réponses

1 2
Avatar
Stephane CHAZELAS
2008-11-07, 14:20(+00), Kevin Denis:
Bonjour,

je dois trier un très grand nombre de fichiers qui contiennent une
ou plusieurs fois une pattern.

Je fais donc un grep, suivi d'un sort -u pour avoir une fois
uniquement les fichiers.
Est il possible avec grep de donner le nom du fichier une seule fois?

La commande est:
find directory/ -type f -exec grep "pattern" {} ; -print > /tmp/liste

Est il possible de n'avoir que le nom des fichiers comportant
pattern d'une manière plus élégante?



find directory -type f -exec grep -l 'pattern' {} +

ou

find directory -type f -exec grep -q 'pattern' {} ; -print
mais ca lance un grep par fichier.

Voir aussi le

grep -rl pattern directory

du GNU grep (attention aux symlinks toutefois).

--
Stéphane
Avatar
Kevin Denis
Le 07-11-2008, Stephane CHAZELAS a écrit :
je dois trier un très grand nombre de fichiers qui contiennent une
ou plusieurs fois une pattern.
Est il possible avec grep de donner le nom du fichier une seule fois?
La commande est:
find directory/ -type f -exec grep "pattern" {} ; -print > /tmp/liste

Est il possible de n'avoir que le nom des fichiers comportant
pattern d'une manière plus élégante?



find directory -type f -exec grep -l 'pattern' {} +



Cela me met missing argument for grep mais
find directory -type f -exec grep -l pattern {};
fonctionne bien, merci

ou

find directory -type f -exec grep -q 'pattern' {} ; -print
mais ca lance un grep par fichier.

Voir aussi le

grep -rl pattern directory

du GNU grep (attention aux symlinks toutefois).



C'est le find et le grep de busybox.
--
Kevin
Avatar
Alain Montfranc
Kevin Denis a écrit
Le 07-11-2008, Stephane CHAZELAS a écrit :
je dois trier un très grand nombre de fichiers qui contiennent une
ou plusieurs fois une pattern.
Est il possible avec grep de donner le nom du fichier une seule fois?
La commande est:
find directory/ -type f -exec grep "pattern" {} ; -print > /tmp/liste

Est il possible de n'avoir que le nom des fichiers comportant
pattern d'une manière plus élégante?



find directory -type f -exec grep -l 'pattern' {} +



Cela me met missing argument for grep mais
find directory -type f -exec grep -l pattern {};
fonctionne bien, merci





Si tu as xargs :

find directory -type f -print0 | xargs -0 grep -l pattern

est beaucoup plus efficace
Avatar
Kevin Denis
Le 07-11-2008, Alain Montfranc a écrit :
je dois trier un très grand nombre de fichiers qui contiennent une
ou plusieurs fois une pattern.
Est il possible avec grep de donner le nom du fichier une seule fois?
La commande est:
find directory/ -type f -exec grep "pattern" {} ; -print > /tmp/liste

Est il possible de n'avoir que le nom des fichiers comportant
pattern d'une manière plus élégante?



find directory -type f -exec grep -l 'pattern' {} +



Cela me met missing argument for grep mais
find directory -type f -exec grep -l pattern {};
fonctionne bien, merci



Si tu as xargs :

find directory -type f -print0 | xargs -0 grep -l pattern

est beaucoup plus efficace



Je pose le problème complet.
Il m'arrive de devoir traiter des spools de mail sendmail
complètement remplis de SPAMs.
Un mail est constitué de deux fichiers, un qf????? et
un [dD]f????, le qf correspond aux entêtes et le df au
corps du mail.

Le but est de chercher dans les qf ceux dont les destinataires
correspondent aux spammés, par exemple ???@yahoo.com.tw

Le find me permet de remonter les fichiers qf, avec
un deuxième traitement, je peux dupliquer les qf en [dD]f
puis enfin lancer la suppression.

Mais lorsque les spools sont remplis de +500000 mails,
c'est long. J'attends le résultat du find (c'est long),
puis je scripte la suppression. De plus la commande fait
monter la charge de la machine, ce qui n'est pas forcément
souhaitable.

Ma question:
comment lancer en un one-liner la commande qui va
à partir de la pattern (par ex yahoo.com.tw), chercher
le qf, le df associé et les supprimer. Ainsi, je
peux lancer une fois la commande, et faire autre
chose.
Merci
--
Kevin
Avatar
Alain Montfranc
Kevin Denis a écrit
Le 07-11-2008, Alain Montfranc a écrit :
je dois trier un très grand nombre de fichiers qui contiennent une
ou plusieurs fois une pattern.
Est il possible avec grep de donner le nom du fichier une seule fois?
La commande est:
find directory/ -type f -exec grep "pattern" {} ; -print > /tmp/liste

Est il possible de n'avoir que le nom des fichiers comportant
pattern d'une manière plus élégante?



find directory -type f -exec grep -l 'pattern' {} +



Cela me met missing argument for grep mais
find directory -type f -exec grep -l pattern {};
fonctionne bien, merci



Si tu as xargs :

find directory -type f -print0 | xargs -0 grep -l pattern

est beaucoup plus efficace



Je pose le problème complet.
Il m'arrive de devoir traiter des spools de mail sendmail
complètement remplis de SPAMs.
Un mail est constitué de deux fichiers, un qf????? et
un [dD]f????, le qf correspond aux entêtes et le df au
corps du mail.

Le but est de chercher dans les qf ceux dont les destinataires
correspondent aux spammés, par exemple ???@yahoo.com.tw

Le find me permet de remonter les fichiers qf, avec
un deuxième traitement, je peux dupliquer les qf en [dD]f
puis enfin lancer la suppression.

Mais lorsque les spools sont remplis de +500000 mails,
c'est long. J'attends le résultat du find (c'est long),
puis je scripte la suppression. De plus la commande fait
monter la charge de la machine, ce qui n'est pas forcément
souhaitable.

Ma question:
comment lancer en un one-liner la commande qui va
à partir de la pattern (par ex yahoo.com.tw), chercher
le qf, le df associé et les supprimer. Ainsi, je
peux lancer une fois la commande, et faire autre
chose.
Merci



Bon ce sont des fichiers de spool donc des noms sympas (sans expace).
Le truc suivant doit marcher :

find directory -type f -print | xargs grep -l pattern | sed
's/qf(.*)/& df1 Df1' | xargs rm -f
Avatar
Freddy DISSAUX
Le 08 Nov 2008 11:50:50 GMT, Kevin écrivait:
[ snip grep -l, find, xargs ]

Je pose le problème complet.


Voila, on va y voir plus clair

Il m'arrive de devoir traiter des spools de mail sendmail
complètement remplis de SPAMs.
Un mail est constitué de deux fichiers, un qf????? et
un [dD]f????, le qf correspond aux entêtes et le df au
corps du mail.


Ok


Le but est de chercher dans les qf ceux dont les destinataires
correspondent aux spammés, par exemple ???@yahoo.com.tw



Ok

Le find me permet de remonter les fichiers qf, avec
un deuxième traitement, je peux dupliquer les qf en [dD]f
puis enfin lancer la suppression.



Ok

Mais lorsque les spools sont remplis de +500000 mails,
c'est long. J'attends le résultat du find (c'est long),
puis je scripte la suppression. De plus la commande fait
monter la charge de la machine, ce qui n'est pas forcément
souhaitable.



Ok

Ma question:
comment lancer en un one-liner la commande qui va
à partir de la pattern (par ex yahoo.com.tw), chercher
le qf, le df associé et les supprimer. Ainsi, je
peux lancer une fois la commande, et faire autre
chose.
Merci


On récapitule:
- trouver les fichiers dont le contenu match <pattern>
- à partir du nom du fichier, en déduire un autre
- supprimer les deux fichiers

Je ne pense pas que la combinaison find, grep, xargs puissent en une
seule ligne répondre au besoin.

Une longue (voire interminable) ligne de commande mettant en oeuvre
moultes outils n'est pas toujours plus performante un script shell (ou
perl).

Un début de réponse:

#!/usr/bin/perl

use strict;
use warnings;

sub process_file {
my ($file, $dir, $pattern) = @_;
open (my $fh, '<', "$dir/$file") || die "Pb open $dir/$file: $!";
my @lines = <$fh>;
close($fh);
if (grep { /$pattern/ } @lines) { delete_file($file, $dir) }
}

sub process_dir {
my ($dir, $pattern) = @_;
opendir (my $DIR, $dir) || die "Pb opendir $dir: $!";
map { -f $_ && process_file($_, $dir, $pattern) } readdir($DIR);
closedir($DIR);
}

sub delete_file {
my ($file, $dir) = @_;
print "suppression de $dir/$filen";
}

my $pattern = shift;
map { process_dir($_, $pattern) } @ARGV;

./script.pl <pattern> <liste des répertoires à traiter>

Suivant le nombre de pattern à traiter, une regexp de velu, un peu de
shell ou une autre boucle par pattern.

En espérant avoir aidé.
--
freddy <point> dsx <arobase> free <point> fr
Avatar
Alain Montfranc
Freddy DISSAUX a écrit
Le 08 Nov 2008 11:50:50 GMT, Kevin écrivait:
[ snip grep -l, find, xargs ]

Je pose le problème complet.


Voila, on va y voir plus clair

Il m'arrive de devoir traiter des spools de mail sendmail
complètement remplis de SPAMs.
Un mail est constitué de deux fichiers, un qf????? et
un [dD]f????, le qf correspond aux entêtes et le df au
corps du mail.


Ok


Le but est de chercher dans les qf ceux dont les destinataires
correspondent aux spammés, par exemple ???@yahoo.com.tw



Ok

Le find me permet de remonter les fichiers qf, avec
un deuxième traitement, je peux dupliquer les qf en [dD]f
puis enfin lancer la suppression.



Ok

Mais lorsque les spools sont remplis de +500000 mails,
c'est long. J'attends le résultat du find (c'est long),
puis je scripte la suppression. De plus la commande fait
monter la charge de la machine, ce qui n'est pas forcément
souhaitable.



Ok

Ma question:
comment lancer en un one-liner la commande qui va
à partir de la pattern (par ex yahoo.com.tw), chercher
le qf, le df associé et les supprimer. Ainsi, je
peux lancer une fois la commande, et faire autre
chose.
Merci


On récapitule:
- trouver les fichiers dont le contenu match <pattern>
- à partir du nom du fichier, en déduire un autre
- supprimer les deux fichiers

Je ne pense pas que la combinaison find, grep, xargs puissent en une
seule ligne répondre au besoin.

Une longue (voire interminable) ligne de commande mettant en oeuvre
moultes outils n'est pas toujours plus performante un script shell (ou
perl).

Un début de réponse:

#!/usr/bin/perl

use strict;
use warnings;

sub process_file {
my ($file, $dir, $pattern) = @_;
open (my $fh, '<', "$dir/$file") || die "Pb open $dir/$file: $!";
my @lines = <$fh>;
close($fh);
if (grep { /$pattern/ } @lines) { delete_file($file, $dir) }
}

sub process_dir {
my ($dir, $pattern) = @_;
opendir (my $DIR, $dir) || die "Pb opendir $dir: $!";
map { -f $_ && process_file($_, $dir, $pattern) } readdir($DIR);
closedir($DIR);
}

sub delete_file {
my ($file, $dir) = @_;
print "suppression de $dir/$filen";
}

my $pattern = shift;
map { process_dir($_, $pattern) } @ARGV;

./script.pl <pattern> <liste des répertoires à traiter>

Suivant le nombre de pattern à traiter, une regexp de velu, un peu de
shell ou une autre boucle par pattern.

En espérant avoir aidé.



Je préfére mon

find directory -type f -print | xargs grep -l pattern | sed
's/qf(.*)/& df1 Df1' | xargs rm -f

;-)
Avatar
Alain Montfranc
(supersedes )

Freddy DISSAUX a écrit
Le 08 Nov 2008 11:50:50 GMT, Kevin écrivait:
[ snip grep -l, find, xargs ]

Je pose le problème complet.


Voila, on va y voir plus clair

Il m'arrive de devoir traiter des spools de mail sendmail complètement
remplis de SPAMs.
Un mail est constitué de deux fichiers, un qf????? et
un [dD]f????, le qf correspond aux entêtes et le df au
corps du mail.


Ok


Le but est de chercher dans les qf ceux dont les destinataires
correspondent aux spammés, par exemple ???@yahoo.com.tw



Ok

Le find me permet de remonter les fichiers qf, avec
un deuxième traitement, je peux dupliquer les qf en [dD]f
puis enfin lancer la suppression.



Ok

Mais lorsque les spools sont remplis de +500000 mails,
c'est long. J'attends le résultat du find (c'est long), puis je scripte la
suppression. De plus la commande fait
monter la charge de la machine, ce qui n'est pas forcément souhaitable.



Ok

Ma question:
comment lancer en un one-liner la commande qui va
à partir de la pattern (par ex yahoo.com.tw), chercher
le qf, le df associé et les supprimer. Ainsi, je
peux lancer une fois la commande, et faire autre
chose.
Merci


On récapitule:
- trouver les fichiers dont le contenu match <pattern>
- à partir du nom du fichier, en déduire un autre
- supprimer les deux fichiers

Je ne pense pas que la combinaison find, grep, xargs puissent en une
seule ligne répondre au besoin.

Une longue (voire interminable) ligne de commande mettant en oeuvre
moultes outils n'est pas toujours plus performante un script shell (ou
perl).

Un début de réponse:

#!/usr/bin/perl

use strict;
use warnings;

sub process_file {
my ($file, $dir, $pattern) = @_;
open (my $fh, '<', "$dir/$file") || die "Pb open $dir/$file: $!";
my @lines = <$fh>;
close($fh);
if (grep { /$pattern/ } @lines) { delete_file($file, $dir) }
}

sub process_dir {
my ($dir, $pattern) = @_;
opendir (my $DIR, $dir) || die "Pb opendir $dir: $!";
map { -f $_ && process_file($_, $dir, $pattern) } readdir($DIR);
closedir($DIR);
}

sub delete_file {
my ($file, $dir) = @_;
print "suppression de $dir/$filen";
}

my $pattern = shift;
map { process_dir($_, $pattern) } @ARGV;

./script.pl <pattern> <liste des répertoires à traiter>

Suivant le nombre de pattern à traiter, une regexp de velu, un peu de
shell ou une autre boucle par pattern.

En espérant avoir aidé.



Je préfére mon

find directory -type f -print | xargs grep -l pattern | sed
's/qf(.*)/& df1 Df1' | xargs rm -f

Qu'on peut simplifier (si le grep accepte la recursivité ce qui n'est
pas gagné si je me souviens des messages précédents) :

grep -lr pattern <directeory>| sed 's/qf(.*)/& df1 Df1' | xargs rm
-f
Avatar
Jacques L'helgoualc'h
Bonjour,

Le 08-11-2008, Alain Montfranc a écrit :
[...]
Je préfére mon

find directory -type f -print | xargs grep -l pattern | sed
's/qf(.*)/& df1 Df1' | xargs rm -f

Qu'on peut simplifier (si le grep accepte la recursivité ce qui n'est
pas gagné si je me souviens des messages précédents) :

grep -lr pattern <directeory>| sed 's/qf(.*)/& df1 Df1' | xargs rm
-f



Oui, mais

- tu greppes tous les fichiers, pas seulement les qf ;

- « qf » peut se retrouver ailleurs dans le chemin...

find repert/ -type f -name qf* -exec grep -l REGEXP {} + |
sed -re 's,^(.*/)qf([^/]*)$,& 1df2 1Df2,' |
...

(GNU find & sed).
--
Jacques L'helgoualc'h
Avatar
Alain Montfranc
Jacques L'helgoualc'h a écrit
Bonjour,

Le 08-11-2008, Alain Montfranc a écrit :
[...]
Je préfére mon

find directory -type f -print | xargs grep -l pattern | sed
's/qf(.*)/& df1 Df1' | xargs rm -f

Qu'on peut simplifier (si le grep accepte la recursivité ce qui n'est
pas gagné si je me souviens des messages précédents) :

grep -lr pattern <directeory>| sed 's/qf(.*)/& df1 Df1' | xargs rm
-f



Oui, mais

- tu greppes tous les fichiers, pas seulement les qf ;



exact

- « qf » peut se retrouver ailleurs dans le chemin...



exact


find repert/ -type f -name qf* -exec grep -l REGEXP {} + |
sed -re 's,^(.*/)qf([^/]*)$,& 1df2 1Df2,' |
...



Ah non là c'est crade. Ca lance un grep pour chaque fichier ! Utilises
au moins xargs

cd repertoire; find . -type f -name "qf*" -print | xargs grep -l
pattern | sed 's?^./qf(.*)?& df1 Df1?' | xargs rm -f


(GNU find & sed).


1 2