Comment utiliser> dans une commande xargs?
Question
Je veux trouver une commande bash qui me permettra de grep tous les fichiers dans un répertoire et écrire la sortie de cette grep dans un fichier séparé. Je pense aurait été de faire quelque chose comme ceci
ls -1 | xargs -I{} "grep ABC '{}' > '{}'.out"
mais, autant que je sache, xargs n'aime pas les guillemets doubles. Si je supprime les guillemets, cependant, la commande redirige la sortie de l'ensemble de la commande d'un seul fichier appelé « {} ». Out au lieu de une série de fichiers individuels.
Quelqu'un sait-il d'une façon de le faire en utilisant xargs? Je viens d'utiliser ce scénario grep comme exemple pour illustrer mon problème avec xargs donc des solutions qui n'utilisent pas xargs ne sont pas aussi applicables pour moi.
La solution
Ne faites pas l'erreur de faire ceci:
sh -c "grep ABC {} > {}.out"
Ceci brisera sous beaucoup de conditions, y compris les noms de fichiers funky et il est impossible de citer à droite. Votre doit toujours être {}
un seul argument complètement séparé à la commande pour éviter les bugs d'injection de code. Ce que vous devez faire, est la suivante:
xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}
applique à xargs
ainsi que find
.
Par ailleurs, ne jamais utiliser xargs sans l'option -0
(sauf pour un temps très rare et contrôlé utilisation interactive où vous n'êtes pas inquiet pour détruire vos données).
Aussi, ne pas analyser ls
. Déjà. Utilisez les jokers ou au lieu <=>: http://mywiki.wooledge.org/ParsingLs
Utilisez pour tout ce qui <=> a besoin récursion et une boucle simple avec un glob pour tout le reste:
find /foo -exec sh -c 'grep "$1" > "$1.out"' -- {} \;
ou non récursif:
for file in *; do grep "$file" > "$file.out"; done
Remarquez l'utilisation correcte des guillemets.
Autres conseils
Une solution sans xargs
est la suivante:
find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;
... et la même chose peut être fait avec <=>, il se trouve:
ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"
Modifier : guillemets simples ajoutés après la remarque de lhunath .
Je suppose que votre exemple est juste un exemple et que vous pourriez avoir besoin> pour d'autres choses. http://www.gnu.org/software/parallel/ peut-être votre secours . Il n'a pas besoin de citer tant à mesure que vos noms de fichiers ne contiennent pas \ n:
ls | parallel "grep ABC {} > {}.out"
Si vous avez des noms de fichiers avec \ n en elle:
find . -print0 | parallel -0 "grep ABC {} > {}.out"
En prime vous obtenez les travaux sont exécutés en parallèle.
Modifier.
Vous pouvez installer GNU Parallel simplement par:
wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
Regardez les vidéos d'introduction pour en savoir plus: http://pi.dk/1
10 secondes d'installation:
wget pi.dk/3 -qO - | sh -x