Bash: existe-t-il un moyen de rechercher une chaîne particulière dans un répertoire de fichiers? [dupliquer]

47

Dupliquer possible:
rechercher un modèle de texte sous linux

Sous Bash, je me demandais s’il existait des commandes permettant de savoir si une chaîne particulière que vous recherchez existe dans les fichiers situés dans le répertoire actuel dans lequel vous vous trouvez.

Supposons que vous cherchiez la fonction 'toUpperCase ()' dans un ensemble de fichiers C de votre répertoire actuel. Il y a beaucoup de fichiers, vous ne voudriez donc pas les ouvrir manuellement à l'aide de vim et vérifier la chaîne 'toUpperCase' car cela prendrait beaucoup de temps. Si ce n'est pas une ligne de commande bash, existe-t-il une autre méthode pour le faire efficacement?

Templier noir
la source

Réponses:

64

Avec grep:

grep -R "toUppercase()" *

Ou, si vous avez installé ack-grep , simplement:

ack-grep "toUppercase"

Si vous souhaitez limiter la recherche dans les fichiers C, avec ack-grep:

ack-grep -cc "toUppercase()"

ack-greppeut également être installé sur OSX mais l'exécutable est appelé simplement ack.

Trasplazio Garzuglio
la source
A tel point que SO a déjà une question étrangement similaire ;)
David Perry
10

L'outil de recherche de texte standard est grep .

Pour rechercher la chaîne toUpperCase(dans tous les .cfichiers du répertoire actuel:

grep -F 'toUpperCase(' *.c

Si vous souhaitez également consulter les sous-répertoires:

grep -r --include='*.c' -F 'toUpperCase('

Si vous recherchez des appels de fonction C, les balises ctags peuvent constituer un meilleur ajustement. Vous l'exécutez une fois sur tous vos fichiers source pour créer un index d'identifiants, puis utilisez votre éditeur pour naviguer entre les appels. Tous les éditeurs de type vi peuvent utiliser le TAGSfichier ctags . Si vous utilisez Emacs, exécutez le programme similaire etags.

Gilles, arrête de faire le mal
la source
ctagsest utile pour trouver des définitions de fonction , pas des appels de fonction .
JdeBP
6

Vous utilisez vim. Vous avez un outil pour faire cela intégré.

Comme on pouvait s'y attendre, il y a déjà sept réponses à utiliser grep. Mais il semble que je sois la seule personne à ce jour à avoir remarqué dans votre question que vous utilisez vim. En tant que tel, bien que vous puissiez utiliser grepde l'intérieur vim, vous pouvez également utiliser viml'outil intégré. Ceci est appelé via la :vimgrepcommande.

Pour rechercher "tous les fichiers source C dans le répertoire en cours pour les appels à la fonction toUpperCase()", vimtapez la commande

:vimgrep "\<toUpperCase\_s*(" *.c

La liste de correspondances résultante est automatiquement chargée dans la liste des correctifs rapides, accessible avec l’un des deux (voir l’aide en ligne pour connaître la différence subtile).

:copen
:cwin

Pour trouver la définition de la fonction , plutôt que de l'appeler, ctagsutilisez l'outil, comme indiqué dans Gillesla réponse de , en conjonction avec les commandes :tjumpou :tselect.

Pourquoi utiliser :vimgrep?

La fonction help ( :help grep) en ligne énumère plusieurs des raisons que je ne vais pas mentionner ici. En plus de celles-ci, comparez l’action de :vimgrepavec celle de dietbuddha' . dietbuddhaLa ligne de commande de sks lance un grepprocessus individuel pour chaque fichier source C individuel. Il n'emploie même pas xargspour réduire ces frais généraux. Et il vous reste à analyser la sortie pour appeler votre éditeur de texte sur les fichiers sources pertinents une fois que celui-ci est terminé. :vimgrepne déclenche pas du tout plusieurs processus supplémentaires, et utiliser le résultat est la simplicité même. Le simple fait de sélectionner l'une des entrées de la liste de correctifs rapides résultante positionne automatiquement le curseur sur la ligne appropriée du fichier source correspondant.

En fait, il fait exactement ce que vous avez écrit à la main, sauf automatiquement. C'est la manière automatisée de faire ces actions d'éditeur de texte. Il charge le fichier comme s'il était chargé à la main, recherche une expression régulière (en utilisant la même syntaxe d'expression régulière que celle que vous utilisez déjà ailleurs vim), enregistre les emplacements où les correspondances se produisent, puis décharge le fichier.

JdeBP
la source
2

Oui, l'outil s'appelle grep.

La commande grep recherche dans un ou plusieurs fichiers d'entrée les lignes contenant une correspondance avec un modèle spécifié. Par défaut, grep affiche les lignes correspondantes.

L'utilisation de base est:

grep something somewhere

Ou plus spécifiquement:

grep [some options] pattern file

Dans un cas très simple, vous souhaitez récursivement rechercher dans tous les fichiers, vous indiquez donc l' -roption. Si vous ne vous souciez pas des majuscules ou des minuscules, faites en sorte que l' -ioption soit insensible à la casse .

grep -ri "touppercase()" .

Si vous ne voulez que les pièces correspondantes, utilisez l' -ooption.

Grep peut utiliser des expressions régulières et dispose d’un manuel énorme .

slhck
la source
2

grepest la réponse standard - en utilisant l’indicateur -r pour effectuer une recherche récursive ou en conjonction avec find(discussion et exemples dans d’autres questions de ce site, comme celle-ci )

Mon choix préféré est dernièrement ack. Il n'est probablement pas installé sur votre ordinateur, mais vous pouvez l'installer à l'aide d'apt-get sur Ubuntu ou simplement le télécharger. Les liens, les instructions et les raisons pour lesquelles il vaut mieux que grep sont disponibles à l' adresse http://betterthangrep.com/

Doug Harris
la source
1

find et grep

find myproject -name '*.c' -exec grep 'toUpperCase(' {} \; -print

pourquoi non seulement grep?

grep -r string .recurse dans tous les fichiers du répertoire en cours. Si vous avez des fichiers objet ou d’autres fichiers binaires, vous pouvez obtenir une correspondance avec des résultats binaires. déchet. Si vous avez également des fichiers fifos ou de périphérique dans votre sous-répertoire, vous risquez d’avoir des conséquences inconnues ou inattendues.

grep string *.crecherche uniquement dans les .cfichiers de répertoires actuels .

grep string **/*.c effectue une recherche dans tous les sous-répertoires. Toutefois, si vous avez un très grand nombre de .cfichiers, vous courez le risque de dépasser le nombre maximal d’expansions pour le shell global. L’expansion doit également avoir lieu en premier, ce qui signifie une traversée complète de l’arbre avant de grepcommencer.

dietbuddha
la source
0

Grep fera l'affaire, mais un peu de script supplémentaire aidera à trouver le nom du fichier et la ligne exacte référencée. Si c'est ce que vous voulez, je trouve que ce qui suit fonctionne bien. Je l'ai enregistré en tant que script shell et transmettez-lui la valeur que je veux comme première option de ligne de commande.

for i in $(ls)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?
    if [ $STATUS  -eq 0 ] ; then
        echo $i
        cat $i | grep -n $1
    fi
done
Tim Brigham
la source
3
grep a une option -H qui le fait déjà. grep -Hn que ce soit *
Roy Rico
Apprenez quelque chose de nouveau chaque jour .. Merci @Roy Rico
Tim Brigham
0

Je trouve intéressant que personne n’ait répondu à votre question précise: "Comment savoir si une chaîne particulière existe dans les fichiers situés dans le répertoire actuel". Autant que je sache, il n'y a pas d'option grep qui indique uniquement si une correspondance a été trouvée dans un groupe de fichiers. L'option la plus proche est -l pour lister le ou les noms de fichiers. La réponse la plus proche parmi ceux-ci est de tim, avec quelques légères modifications:

#!/usr/bin/bash

for i in $(ls *.c 2> /dev/null)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?

    if [ $STATUS  -eq 0 ] ; then
        echo "Found"
        exit
    fi
done

echo "Not found"

Vous pouvez rendre ce script shell plus générique en acceptant un second argument pour l'extension de fichier sans trop de difficulté.

doug

SnoopDougieDoug
la source