Comment est-ce que je grep les 50 premières lignes de chaque fichier dans un répertoire récursivement?

10

J'ai besoin de rechercher les 50 premières lignes de chaque fichier dans un répertoire et ses sous-répertoires.

Cela fera la partie récursive, mais comment puis-je limiter aux 50 premières lignes de chaque fichier?

grep -r "matching string here" .

Certains de ces fichiers sont énormes et je veux seulement qu'ils correspondent dans les 50 premières lignes. J'essaie d'accélérer le processus en ne recherchant pas des mégaoctets de données binaires dans certains fichiers.

zevlag
la source
voulez-vous simplement connaître les fichiers qui correspondent, ou voulez-vous avoir seulement la chaîne correspondante ou voulez-vous la chaîne correspondante avec le nom de fichier?
gniourf_gniourf

Réponses:

11
  • Si vous voulez juste les fichiers qui correspondent:

    find . -type f -exec bash -c 'grep -q "matching string here" < <(head -n 50 "$1")' _ {} \; -printf '%p\n'
    

    ou

    find . -type f -exec bash -c 'grep -q "matching string here" < <(head -n 50 "$1") && printf '%s\n' "$1"' _ {} \;
    
  • Si vous souhaitez uniquement les chaînes correspondantes:

    find . -type f -exec head -n 50 {} \; | grep "matching string here"
    

    ou mieux,

    find . -type f -exec head -q -n 50 {} + | grep "matching string here"
    
  • Et si vous voulez les deux:

    find . -type f -exec bash -c 'mapfile -t a < <(head -n 50 "$1" | grep "matching string here"); printf "$1: %s\n" "${a[@]}"' _ {} \;
    

Remarques.

  • Pourrait être un peu plus facile avec sedau lieu du combo head- grep.
  • Permettez-moi de souligner que les trois méthodes sont 100% sûres en ce qui concerne les noms de fichiers qui peuvent contenir des symboles amusants (espaces, nouvelles lignes, etc.).
  • Dans deux de ces méthodes, je suppose que vous disposez d'une version décemment récente de bash.
  • Vous pouvez utiliser -exec ... +dans chaque méthode, mais vous devrez ensuite coder vous-même votre boucle intérieure! (exercice trivial laissé au lecteur). Cela pourrait être très légèrement plus efficace si vous avez des fichiers de gazillion.
gniourf_gniourf
la source
4

Si vous avez besoin de la sortie grep comme dans l'original, vous pouvez faire:

find . -type f | while read f; do 
  if head -n 50 "$f"|grep -s "matching string here"; then
    grep "matching string here" "$f" /dev/null 
  fi
done

Si vous n'avez besoin que des noms de fichiers, vous pouvez remplacer le 2e grep par echo "$f".

Michael Suelmann
la source
1

Vous devrez combiner plusieurs utilitaires différents pour obtenir la fonctionnalité souhaitée. Utilisez la findcommande pour récupérer les répertoires, rechercher tous les fichiers et exécuter la headcommande sur chaque fichier trouvé. La headcommande peut être utilisée pour vider uniquement les 50 premières lignes de chaque fichier. Enfin, dirigez la sortie vers grep pour rechercher la chaîne souhaitée.

find . -type f -exec head -n 50 {} ";" | grep "matching string here"

Les poils du chien
la source