J'utilise souvent la find
commande pour rechercher dans le code source, supprimer des fichiers, peu importe. Chose ennuyeuse, parce que Subversion stocke des doublons de chaque fichier dans ses .svn/text-base/
répertoires, mes recherches simples finissent par obtenir de nombreux résultats en double. Par exemple, je veux rechercher récursivement uint
dans plusieurs fichiers messages.h
et messages.cpp
:
# find -name 'messages.*' -exec grep -Iw uint {} +
./messages.cpp: Log::verbose << "Discarding out of date message: id " << uint(olderMessage.id)
./messages.cpp: Log::verbose << "Added to send queue: " << *message << ": id " << uint(preparedMessage->id)
./messages.cpp: Log::error << "Received message with invalid SHA-1 hash: id " << uint(incomingMessage.id)
./messages.cpp: Log::verbose << "Received " << *message << ": id " << uint(incomingMessage.id)
./messages.cpp: Log::verbose << "Sent message: id " << uint(preparedMessage->id)
./messages.cpp: Log::verbose << "Discarding unsent message: id " << uint(preparedMessage->id)
./messages.cpp: for (uint i = 0; i < 10 && !_stopThreads; ++i) {
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Discarding out of date message: id " << uint(olderMessage.id)
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Added to send queue: " << *message << ": id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base: Log::error << "Received message with invalid SHA-1 hash: id " << uint(incomingMessage.id)
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Received " << *message << ": id " << uint(incomingMessage.id)
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Sent message: id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Discarding unsent message: id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base: for (uint i = 0; i < 10 && !_stopThreads; ++i) {
./virus/messages.cpp:void VsMessageProcessor::_progress(const string &fileName, uint scanCount)
./virus/messages.cpp:ProgressMessage::ProgressMessage(const string &fileName, uint scanCount)
./virus/messages.h: void _progress(const std::string &fileName, uint scanCount);
./virus/messages.h: ProgressMessage(const std::string &fileName, uint scanCount);
./virus/messages.h: uint _scanCount;
./virus/.svn/text-base/messages.cpp.svn-base:void VsMessageProcessor::_progress(const string &fileName, uint scanCount)
./virus/.svn/text-base/messages.cpp.svn-base:ProgressMessage::ProgressMessage(const string &fileName, uint scanCount)
./virus/.svn/text-base/messages.h.svn-base: void _progress(const std::string &fileName, uint scanCount);
./virus/.svn/text-base/messages.h.svn-base: ProgressMessage(const std::string &fileName, uint scanCount);
./virus/.svn/text-base/messages.h.svn-base: uint _scanCount;
Comment puis-je dire find
d'ignorer les .svn
répertoires?
Mise à jour : si vous mettez à niveau votre client SVN vers la version 1.7, ce n'est plus un problème.
Une caractéristique clé des changements introduits dans Subversion 1.7 est la centralisation du stockage des métadonnées de copie de travail en un seul emplacement. Au lieu d'un
.svn
répertoire dans chaque répertoire de la copie de travail, les copies de travail de Subversion 1.7 n'ont qu'un seul.svn
répertoire, à la racine de la copie de travail. Ce répertoire comprend (entre autres) une base de données SQLite-soutenue qui contient tous les besoins de Subversion de métadonnées pour cette copie de travail.
find ... -print0 | xargs -0 egrep ...
place defind ... -exec grep ...
(ne se bifurque pasgrep
pour chaque fichier, mais pour un tas de fichiers à la fois). En utilisant ce formulaire, vous pouvez également élaguer les.svn
répertoires sans utiliser l'-prune
option de recherche, c'estfind ... -print0 | egrep -v '/\.svn' | xargs -0 egrep ...
-exec
avec+
ne se bifurque pasgrep
pour chaque fichier, tout en l'utilisant avec le;
fait. L'utilisation-exec
est en fait plus correcte que l'utilisationxargs
. Veuillez noter que les commandes commels
font quelque chose même si la liste des arguments est vide, tandis que les commandes commechmod
donnent une erreur s'il n'y a pas suffisamment d'arguments. Pour voir ce que je veux dire, essayez la commande suivante dans un répertoire qui n'a pas de script shell:find /path/to/dir -name '*.sh' -print0 | xargs -0 chmod 755
. Comparer avec celui - ci:find /path/to/dir -name '*.sh' -exec chmod 755 '{}' '+'
.grep
sortir.svn
n'est pas une bonne idée non plus. Bien qu'ilfind
soit spécialisé dans la gestion des propriétés des fichiers, ilgrep
ne l'est pas. Dans votre exemple, un fichier nommé '.svn.txt' sera également filtré par votreegrep
commande. Bien que vous puissiez modifier votre expression régulière en '^ / \. Svn $' , ce n'est toujours pas une bonne pratique de le faire. Le-prune
prédicat defind
fonctionne parfaitement pour filtrer un fichier (par nom de fichier, ou horodatage de création, ou quelle que soit la condition que vous avez fournie). C'est comme si même si vous pouvez tuer un cafard à l'aide d'une grosse épée, cela ne signifie pas que c'est la façon suggérée de le faire :-).Réponses:
Pour la recherche, puis-je vous suggérer de regarder ack ? Il s'agit d'un code source
find
, et en tant que tel, il ignorera automatiquement de nombreux types de fichiers, y compris les informations de référentiel de code source telles que celles ci-dessus.la source
ack
beaucoup, mais je l'ai trouvé beaucoup plus lent quefind -type f -name "*.[ch]" | xargs grep
lorsqu'il s'agissait d'une grande base de code.ack
facturé comme meilleurgrep
, pas comme source-conscientfind
? Quelques exemples d'utilisation pour le remplacer enfind
feraient une vraie réponse.pourquoi pas
Le prédicat -not annule tout ce qui contient .svn n'importe où dans le chemin.
Donc, dans votre cas, ce serait
la source
'*.svn*'
au début mais ensuite'*.svn'
. Quelle est la bonne? Les deux fonctionnent-ils? Je pense que ça devrait probablement l'être'*.svn*'
?Comme suit:
Ou bien, basé sur un répertoire et non sur un préfixe de chemin:
la source
find . -type d -name .svn -prune -o -print
car c'est un peu plus rapide. Selon la norme POSIX , les expressions sont évaluées une par une, dans l'ordre spécifié. Si la première expression de-a
estfalse
, la seconde expression ne sera pas évaluée (également appelée court-circuit et évaluation ).-type d
avant-name .svn
est théoriquement plus efficace. Cependant, il est généralement insignifiant, sauf si vous avez une très grande arborescence de répertoires.-print
dans le cadre de la dernière expression. Quelque chose commefind . -name .git -prune -o \( -type f -name LICENSE -print \)
fonctionne comme prévu.find . -name .svn -prune -o -name .git -prune -o -type d -print
. Cela pourrait être quelques millisecondes plus rapide-type d
avant les deux-name
, mais cela ne vaut pas la peine d'être tapé.Pour ignorer
.svn
,.git
et d'autres répertoires cachés (commençant par un point), essayez:Cependant, si le but de l'utilisation
find
est la recherche dans les fichiers, vous pouvez essayer d'utiliser ces commandes:git grep
- commande spécialement conçue pour rechercher des modèles dans le référentiel Git.ripgrep
- qui ignore par défaut les fichiers cachés et les fichiers spécifiés dans.gitignore
.Connexes: Comment trouver tous les fichiers contenant du texte spécifique sur Linux?
la source
Voici ce que je ferais dans votre cas:
La
rgrep
commande intégrée d' Emacs ignore le.svn
répertoire et bien d'autres fichiers qui ne vous intéressent probablement pas lors de l'exécution d'unfind | grep
. Voici ce qu'il utilise par défaut:Il ignore les répertoires créés par la plupart des systèmes de contrôle de version, ainsi que les fichiers générés pour de nombreux langages de programmation. Vous pouvez créer un alias qui invoque cette commande et remplacer
find
et desgrep
modèles pour vos problèmes spécifiques.la source
GNU find
la source
-type d
) - cette réponse l'a fait. +1J'utilise grep à cet effet. Mettez ceci dans votre ~ / .bashrc
grep utilise automatiquement ces options lors de l'invocation
la source
GREP_OPTIONS=xxx grep "$@"
. Cela signifie que la variable GREP_OPTIONS n'est définie que pour les instances de grep que j'exécute manuellement à l'aide de 'grp'. Cela signifie que je ne reçois jamais de situation où j'exécute un outil et, en interne, il appelle grep, mais l'outil est confus car grep ne se comporte pas comme prévu. En outre, j'ai une deuxième fonction «grpy», qui appelle «grp», mais ajoute--include=*.py
, pour simplement rechercher des fichiers Python.grep --exclude=tags --exclude_dir=.git ...etc... "$@"
. J'aime que cela fonctionne comme «ack», mais je garde la conscience et le contrôle de ce qu'il fait.find . | grep -v \.svn
la source
.
dans l'.svn
expression régulière.| fgrep -v /.svn/
ou `| grep -F -v / .svn / `pour exclure exactement le répertoire et non les fichiers avec" .svn "dans leur nom.Pourquoi ne dirigez-vous pas votre commande avec grep qui est facilement compréhensible:
la source
.
dans l'.svn
expression régulière.Créez un script appelé
~/bin/svnfind
:Ce script se comporte de manière identique à une
find
commande ordinaire mais il élague les.svn
répertoires. Sinon, le comportement est identique.Exemple:
la source
echo
à la commande find et me dire quelle commande est exécutée?svnfind -type f
fonctionne très bien sur ma machine Red Hat.echo find "${OPTIONS[@]}"...
qu'elle imprime la commande find au lieu de l'exécuter.echo find ${OPTIONS[@]} ${PATHS[@]} -name .svn -type d -prune -o ( ${EXPR[@]} ) $ACTION
, Cela me donne la sortie suivante:find -type f -name .svn -type d -prune -o ( -true ) -print
Je pensais juste ajouter une alternative simple à de Kaleb et les messages des autres (qui expose en détail l'utilisation de l'
find -prune
optionack
, desrepofind
commandes , etc.) qui est particulièrement applicable à l'utilisation que vous avez décrite dans la question (et toutes les autres usages similaires):Pour des performances, vous devez toujours essayer d'utiliser
find ... -exec grep ... +
(merci Kenji pour l'avoir signalé) oufind ... | xargs egrep ...
(portable) oufind ... -print0 | xargs -0 egrep ...
(GNU; fonctionne sur les noms de fichiers contenant des espaces) au lieu defind ... -exec grep ... \;
.le
find ... -exec ... +
find | xargs
formulaire et ne se déroule pasegrep
pour chaque fichier, mais plutôt pour un groupe de fichiers à la fois, ce qui entraîne une exécution beaucoup plus rapide .Lorsque vous utilisez le
find | xargs
formulaire, vous pouvez également utilisergrep
pour tailler facilement et rapidement.svn
(ou tout répertoire ou expression régulière), c'est-à-direfind ... -print0 | grep -v '/\.svn' | xargs -0 egrep ...
(utile lorsque vous avez besoin de quelque chose de rapide et que vous ne pouvez pas vous soucier de savoir comment configurerfind
la-prune
logique.)L'
find | grep | xargs
approche est similaire àfind
l'-regex
option de GNU (voirghostdog74
l'article), mais est plus portable (fonctionnera également sur les plates-formes où GNUfind
n'est pas disponible.)la source
-exec
changementfind
: l'une se termine par;
et l'autre se termine par+
. Celui qui se termine par+
remplace{}
par une liste de tous les fichiers correspondants. En outre, votre expression régulière'/\.svn'
correspond également aux noms de fichiers'.svn.txt'
. Veuillez vous référer à mes commentaires sur la question pour plus d'informations.find
utilitaire. Veuillez consulter la-exec
partie :-).Dans un référentiel de code source, je veux généralement faire des choses uniquement avec les fichiers texte.
La première ligne comprend tous les fichiers, à l'exception des fichiers de référentiel CVS, SVN et GIT.
La deuxième ligne exclut tous les fichiers binaires.
la source
J'utilise find avec les options -not -path. Je n'ai pas eu de chance avec le pruneau.
trouvera les fichiers groovy pas dans le chemin du répertoire cible.
la source
Pour résoudre ce problème, vous pouvez simplement utiliser cette condition de recherche:
Vous pouvez ajouter plus de restrictions comme ceci:
Vous pouvez trouver plus d'informations à ce sujet dans la section de la page de manuel "Opérateurs": http://unixhelp.ed.ac.uk/CGI/man-cgi?find
la source
Notez que si vous le faites
find . -type f -name 'messages.*'
-print
est alors implicite lorsque toute l'expression (-type f -name 'messages.*'
) est vraie, car il n'y a pas d '«action» (comme-exec
).Tandis que, pour arrêter de descendre dans certains répertoires, vous devez utiliser tout ce qui correspond à ces répertoires et le suivre
-prune
(qui est destiné à arrêter la descente dans les répertoires); ainsi:find . -type d -name '.svn' -prune
Cela équivaut à True pour les répertoires .svn, et nous pouvons utiliser un court-circuit booléen en suivant ceci par
-o
(OR), après quoi ce qui suit après le-o
n'est vérifié que lorsque la première partie est False, il ne s'agit donc pas d' un répertoire .svn. En d'autres termes, ce qui suit:find . -type d -name '.svn' -prune -o -name 'message.*' -exec grep -Iw uint {}
ne fera que evalute ce qui est juste de
-o
, à savoir-name 'message.*' -exec grep -Iw uint {}
, pour les fichiers NON à l'intérieur des répertoires .svn.Notez que parce qu'il
.svn
s'agit probablement toujours d'un répertoire (et non par exemple d'un fichier), et dans ce cas ne correspond certainement pas au nom 'message. *', Vous pouvez aussi bien laisser de côté le-type d
et faire:find . -name '.svn' -prune -o -name 'message.*' -exec grep -Iw uint {}
Enfin, notez que si vous omettez une action (
-exec
est une action), dites comme ceci:find . -name '.svn' -prune -o -name 'message.*'
alors l'
-print
action est implicite mais s'appliquera à l'expression WHOLE, y compris la-name '.svn' -prune -o
partie et affichera ainsi tous les répertoires .svn ainsi que les fichiers 'message. *', ce qui n'est probablement pas ce que vous voulez. Par conséquent, vous devez toujours utiliser une «action» dans le côté droit de l'expression booléenne lorsque vous utilisez-prune
de cette manière. Et lorsque cette action s'imprime, vous devez l'ajouter explicitement, comme ceci:find . -name '.svn' -prune -o -name 'message.*' -print
la source
Essayez findrepo qui est un simple wrapper autour de find / grep et beaucoup plus rapide que ack Vous l'utiliseriez dans ce cas comme:
la source
wcfind
est un script de wrapper de recherche que j'utilise pour supprimer automatiquement les répertoires .svn.la source
Cela fonctionne pour moi dans l'invite Unix
La commande ci-dessus listera les FICHIERS qui ne sont pas avec .svn et fera le grep que vous avez mentionné.
la source
xxx.svnxxx
. C'est important - par exemple, si vous utilisez git au lieu de svn, vous souhaiterez souvent inclure des fichiers comme .gitignore (qui ne sont pas des métadonnées, c'est un fichier normal qui est inclus dans le repo) dans les résultats de find.Je dirige généralement la sortie via grep une fois de plus en supprimant .svn, dans mon utilisation, ce n'est pas beaucoup plus lent. exemple typique:
OU
la source
Si vous dites à find de rechercher dans '*', alors il sautera tous les "fichiers dot" à la racine:
ou avec chemin
Ce n'est pas une solution exacte / parfaite à la question. Cependant, peu de solutions sont plus simples que celle-ci. Les performances sont également excellentes, car elles n'entrent même pas dans les répertoires cachés.
lacunes:
Donc, dans votre exemple, l'ajout d'une étoile est la seule modification dont vous auriez besoin:
la source