Je veux trouver une commande bash qui me permettra de grep chaque fichier d'un répertoire et d'écrire la sortie de ce grep dans un fichier séparé. J'aurais supposé faire quelque chose comme ça
ls -1 | xargs -I{} "grep ABC '{}' > '{}'.out"
mais, autant que je sache, xargs n'aime pas les guillemets. Cependant, si je supprime les guillemets doubles, la commande redirige la sortie de la commande complète vers un fichier unique appelé "{}".
Est-ce que quelqu'un connaît un moyen de faire cela en utilisant xargs? J'ai simplement utilisé ce scénario grep comme exemple pour illustrer mon problème avec xargs, de sorte que toute solution n'utilisant pas xargs ne me convient pas.
Ne faites pas l'erreur de faire ceci:
sh -c "grep ABC {} > {}.out"
Cela va casser dans beaucoup de conditions, y compris les noms de fichiers funky et il est impossible de citer correctement. Votre {}
doit toujours être un seul argument complètement séparé de la commande pour éviter les bogues d'injection de code. Ce que vous devez faire, c'est ceci:
xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}
S'applique à xargs
ainsi qu'à find
.
En passant, n'utilisez jamais xargs sans le -0
option (sauf en cas d'utilisation interactive unique et très rare et contrôlée ne vous inquiétant pas pour la destruction de vos données).
Aussi, ne pas analyser ls
. Déjà. Utilisez globbing ou find
à la place: http://mywiki.wooledge.org/ParsingLs
Utilisez find
pour tout ce qui nécessite de la récursivité et une simple boucle 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
Notez l'utilisation appropriée des guillemets.
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 faite avec xargs
, il s'avère:
ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"
Modifier : guillemets simples ajoutés après remarque par lhunath .
Je suppose que votre exemple n'est qu'un exemple et que vous pourriez avoir besoin> d'autres choses. GNU Parallel http://www.gnu.org/software/parallel/ peut être votre sauvetage. Il n'a pas besoin de citations supplémentaires tant que vos noms de fichiers ne le sont pas. contient\n:
ls | parallel "grep ABC {} > {}.out"
Si vous avez des noms de fichiers avec\n dedans:
find . -print0 | parallel -0 "grep ABC {} > {}.out"
En prime, les travaux sont exécutés en parallèle.
Modifier.
Vous pouvez installer GNU Parallèle simplement en:
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