Je fais un find
puis j'obtiens une liste de fichiers. Comment puis-je le diriger vers un autre utilitaire comme cat
(de sorte que cat affiche le contenu de tous ces fichiers) et avoir essentiellement besoin de grep
quelque chose de ces fichiers.
Je fais un find
puis j'obtiens une liste de fichiers. Comment puis-je le diriger vers un autre utilitaire comme cat
(de sorte que cat affiche le contenu de tous ces fichiers) et avoir essentiellement besoin de grep
quelque chose de ces fichiers.
Réponses:
Tuyauterie vers un autre processus (bien que cela n'accomplisse pas ce que vous avez dit que vous essayez de faire):
command1 | command2
Cela enverra la sortie de command1 comme entrée de command2
-exec
sur un find
(cela fera ce que vous voulez faire - mais est spécifique à find
)
find . -name '*.foo' -exec cat {} \;
(Tout ce qui se trouve entre find
et -exec
sont les prédicats de recherche que vous utilisiez déjà. {}
Remplacera le fichier particulier que vous avez trouvé dans la commande ( cat {}
dans ce cas); \;
c'est pour terminer la -exec
commande.)
envoyer la sortie d'un processus en tant qu'arguments de ligne de commande à un autre processus
command2 `command1`
par exemple:
cat `find . -name '*.foo' -print`
(Notez que ce ne sont pas des guillemets réguliers (sous le tilde ~ de mon clavier).) Cela enverra la sortie de command1
dans en command2
tant qu'arguments de ligne de commande. Notez que les noms de fichiers contenant des espaces (sauts de ligne, etc.) seront cependant divisés en arguments séparés.
find
vous permettent d'écrire:, find . -name '*.foo' -exec cat {} +
où le +
indique que find
doit regrouper autant de noms de fichiers que possible en une seule invocation de commande. Ceci est très utile (il traite des espaces, etc. dans les noms de fichiers sans recourir à -print0
et xargs -0
).
find . -name '*.foo' | xargs cat
find . -name '*.foo' | xargs cat | grep string
POSIX 2008 a ajouté le +
marqueur, find
ce qui signifie qu'il regroupe désormais automatiquement autant de fichiers qu'il est raisonnable en une seule exécution de commande, tout comme le xargs
fait, mais avec un certain nombre d'avantages:
Le problème du nom de fichier est un problème avec xargs
sans l' -0
option, et le problème "exécuter même avec zéro nom de fichier" est un problème avec ou sans l' -0
option - mais GNU xargs
a l' option -r
ou --no-run-if-empty
pour empêcher que cela ne se produise. En outre, cette notation réduit le nombre de processus, pas que vous êtes susceptible de mesurer la différence de performances. Par conséquent, vous pourriez raisonnablement écrire:
find . -exec grep something {} +
find . -print | xargs grep something
Si vous êtes sous Linux ou avez le GNU find
et les xargs
commandes, utilisez -print0
avec find
et -0
avec xargs
pour gérer les noms de fichiers contenant des espaces et d'autres caractères impairs.
find . -print0 | xargs -0 grep something
grep
Si vous ne voulez pas les noms de fichiers (juste le texte), ajoutez une option appropriée à grep
(généralement -h
pour supprimer les «en-têtes»). Pour garantir absolument que le nom de fichier est imprimé par grep
(même si un seul fichier est trouvé ou si la dernière invocation de grep
n'est donnée que 1 nom de fichier), puis ajoutez /dev/null
à la xargs
ligne de commande, de sorte qu'il y aura toujours au moins deux noms de fichiers.
xargs grep something
.
find
est dirigée vers l'entrée standard de xargs
. Le xargs
programme lit son entrée standard, divise l'entrée à un espace blanc (blancs, sauts de ligne, tabulations, etc.) et ajoute un certain nombre de mots à la commande grep something
et exécute la ligne de commande. xargs
continue ensuite à lire les entrées et à exécuter les commandes jusqu'à ce qu'elles soient épuisées. xargs
exécute la grep
commande aussi souvent que nécessaire pour l'entrée qui lui est donnée (à partir de find
dans cet exemple).
/dev/null
perd les messages d'erreur.
Il existe plusieurs façons de transmettre la liste des fichiers renvoyés par la find
commande à la cat
commande, bien que techniquement tous n'utilisent pas de tuyauterie et qu'aucun ne soit directement dirigé vers cat
.
Le plus simple est d'utiliser des backticks ( `
):
cat `find [whatever]`
Cela prend la sortie de find
et la place effectivement sur la ligne de commande de cat
. Cela ne fonctionne pas bien s'il find
a trop de sortie (plus que ce qui peut tenir sur une ligne de commande) ou si la sortie a des caractères spéciaux (comme des espaces).
Dans certains shells, notamment bash
, on peut utiliser à la $()
place des backticks:
cat $(find [whatever])
C'est moins portable, mais est emboîtable. Mis à part cela, il a à peu près les mêmes mises en garde que les contre-coups.
Parce que l'exécution d'autres commandes sur ce qui a été trouvé est une utilisation courante pour find
, find a une -exec
action qui exécute une commande pour chaque fichier qu'il trouve:
find [whatever] -exec cat {} \;
Le {}
est un espace réservé pour le nom de fichier, et les \;
marques de la fin de la commande (il est possible d'avoir d' autres actions après -exec
.)
Cela s'exécutera cat
une fois pour chaque fichier plutôt que d'exécuter une seule instance en lui cat
passant plusieurs noms de fichiers, ce qui peut être inefficace et ne pas avoir le comportement que vous souhaitez pour certaines commandes (bien que ce soit bien pour cat
). La syntaxe est également difficile à taper - vous devez échapper au point-virgule car le point-virgule est spécial pour le shell!
Certaines versions de find
(notamment la version GNU) vous permettent de remplacer ;
par +
pour utiliser -exec
le mode d'ajout pour exécuter moins d'instances de cat
:
find [whatever] -exec cat {} +
Cela passera plusieurs noms de fichiers à chaque invocation de cat
, ce qui peut être plus efficace.
Notez cependant qu'il n'est pas garanti d'utiliser une seule invocation. Si la ligne de commande est trop longue, les arguments sont répartis sur plusieurs invocations de cat
. Car cat
ce n'est probablement pas un gros problème, mais pour certaines autres commandes, cela peut changer le comportement de manière indésirable. Sur les systèmes Linux, la limite de longueur de ligne de commande est assez grande, donc la division en plusieurs invocations est assez rare par rapport à certains autres systèmes d'exploitation.
L'approche classique / portable consiste à utiliser xargs
:
find [whatever] | xargs cat
xargs
exécute la commande spécifiée ( cat
, dans ce cas) et ajoute des arguments en fonction de ce qu'elle lit depuis stdin. Tout comme -exec
avec +
, cela interrompra la ligne de commande si nécessaire. Autrement dit, si find
produit trop de sortie, il s'exécutera cat
plusieurs fois. Comme mentionné dans la section -exec
précédente, il existe certaines commandes où cette séparation peut entraîner un comportement différent. Notez que l'utilisation de xargs
ce type a des problèmes avec les espaces dans les noms de fichiers, car xargs
utilise simplement des espaces comme délimiteur.
La méthode la plus robuste, portable et efficace utilise également xargs
:
find [whatever] -print0 | xargs -0 cat
L' -print0
indicateur indique find
d'utiliser des \0
délimiteurs (caractère nul) entre les noms de fichiers, et l' -0
indicateur indique xargs
d'attendre ces \0
délimiteurs. Cela a un comportement à peu près identique à l' approche -exec
... +
, bien qu'il soit plus portable (mais malheureusement plus verbeux).
ls
.
$()
également avec des commandes autres que find
.
Cela me semble être un travail pour un script shell:
for file in 'find -name *.xml'
do
grep 'hello' file
done
ou quelque chose comme ça
La commande find a un argument -exec que vous pouvez utiliser pour des choses comme ça, vous pouvez simplement faire le grep directement en utilisant cela.
Par exemple (à partir d'ici, d'autres bons exemples sur cette page ):
find . -exec grep "www.athabasca" '{}' \; -print
En bash, les éléments suivants seraient appropriés:
find /dir -type f -print0 | xargs -0i cat {} | grep whatever
Cela trouvera tous les fichiers dans le /dir
répertoire et xargs
dirigera les noms de fichiers en toute sécurité, qui conduiront en toute sécurité grep
.
Ignorer xargs
n'est pas une bonne idée si vous avez plusieurs milliers de fichiers dans /dir
; cat
se cassera en raison de la longueur excessive de la liste des arguments. xargs
va tout régler pour vous.
L' -print0
argument à find
mailles avec l' -0
argument à xargs
pour gérer correctement les noms de fichiers avec des espaces. L' -i
argument à xargs
vous permet d'insérer le nom de fichier à l'endroit requis dans la cat
ligne de commande. Les crochets sont remplacés par le nom de fichier redirigé vers la cat
commande à partir de find
.
Ça marche pour moi
find _CACHE_* | while read line; do
cat "$line" | grep "something"
done
Utilisez ggrep .
ggrep -H -R -I "mysearchstring" *
rechercher un fichier sous unix contenant du texte situé dans le répertoire courant ou un sous-répertoire
Cela affichera le nom et le contenu des fichiers de manière récursive uniquement.
find . -type f -printf '\n\n%p:\n' -exec cat {} \;
Modifier (version améliorée): Cela imprime le nom et le contenu des fichiers texte (ascii) de manière récursive uniquement.
find . -type f -exec grep -Iq . {} \; -print | xargs awk 'FNR==1{print FILENAME ":" $0; }'
Encore une tentative
find . -type f -exec grep -Iq . {} \; -printf "\n%p:" -exec cat {} \;
Essayez-vous de trouver du texte dans des fichiers? Vous pouvez simplement utiliser grep pour cela ...
grep searchterm *
Pour lister et voir le contenu de tous les fichiers abc.def sur un serveur dans les répertoires / ghi et / jkl
find /ghi /jkl -type f -name abc.def 2> /dev/null -exec ls {} \; -exec cat {} \;
Pour lister les fichiers abc.def qui ont commenté des entrées et les afficher, voyez ces entrées dans les répertoires / ghi et / jkl
find /ghi /jkl -type f -name abc.def 2> /dev/null -exec grep -H ^# {} \;
find -name '*.foo' -print
a très bien fonctionné pour moi ... Merci