Avec les outils GNU:
find . -type f -exec grep -lZ FIND {} + | xargs -r0 grep -l ME
Vous pouvez faire de façon standard:
find . -type f -exec grep -q FIND {} \; -exec grep -l ME {} \;
Mais cela exécuterait deux greps par fichier. Pour éviter d'exécuter autant de grep
s tout en restant portable tout en autorisant tout caractère dans les noms de fichiers, vous pouvez faire:
convert_to_xargs() {
sed "s/[[:blank:]\"\']/\\\\&/g" | awk '
{
if (NR > 1) {
printf "%s", line
if (!index($0, "//")) printf "\\"
print ""
}
line = $0
}'
END { print line }'
}
find .//. -type f |
convert_to_xargs |
xargs grep -l FIND |
convert_to_xargs |
xargs grep -l ME
L'idée étant de convertir la sortie de find
dans un format adapté aux xargs (qui attend un blanc (SPC / TAB / NL, et les autres blancs de votre environnement local avec quelques implémentations de xargs
)) liste séparée de mots où les guillemets simples, doubles et les contre-obliques peuvent échapper aux blancs et les uns aux autres).
En règle générale, vous ne pouvez pas post-traiter la sortie de find -print
, car elle sépare les noms de fichier par un caractère de nouvelle ligne et n'échappe pas aux caractères de nouvelle ligne qui se trouvent dans les noms de fichier. Par exemple, si nous voyons:
./a
./b
Nous n'avons aucun moyen de savoir s'il s'agit d'un fichier appelé b
dans un répertoire appelé a<NL>.
ou s'il s'agit des deux fichiers a
et b
.
En utilisant .//.
, car //
ne peut pas apparaître autrement dans un chemin de fichier en sortie par find
(car il n'y a pas de répertoire avec un nom vide et /
n'est pas autorisé dans un nom de fichier), nous savons que si nous voyons une ligne qui contient //
, alors c'est la première ligne d'un nouveau nom de fichier. Nous pouvons donc utiliser cette awk
commande pour échapper à tous les caractères de nouvelle ligne, sauf ceux qui précèdent ces lignes.
Si nous prenons l'exemple ci-dessus, find
sortirait dans le premier cas (un fichier):
.//a
./b
Quel awk échappe à:
.//a\
./b
Cela le xargs
considère donc comme un argument. Et dans le deuxième cas (deux fichiers):
.//a
.//b
Ce qui awk
resterait tel quel , xargs
voit donc deux arguments.