Comment exécuter plusieurs commandes après xargs -0?
find . -name "filename including space" -print0 | xargs -0 ls -aldF > log.txt
find . -name "filename including space" -print0 | xargs -0 rm -rdf
est-il possible de combiner ces deux commandes en une seule de façon à ce que seulement 1 find soit fait au lieu de 2?
je sais que pour xargs-I il peut y avoir des moyens de le faire, ce qui peut conduire à des erreurs lors de la procédure de noms de fichiers incluant des espaces. Toute orientation est très appréciée.
8 réponses
Si vous êtes juste de vouloir éviter de faire les find
plusieurs fois, vous pourriez faire un tee
juste après find
, l'économie de l' find
sortie vers un fichier, puis exécuter les lignes:
find . -name "filename including space" -print0 | tee my_teed_file | xargs -0 ls -aldF > log.txt
cat my_teed_file | xargs -0 rm -rdf
une autre façon d'accomplir cette même chose (si en effet c'est ce que vous voulez accomplir), est de stocker la sortie du find
dans une variable (supposons que ce ne soit pas TB de données):
founddata=`find . -name "filename including space" -print0`
echo "$founddata" | xargs -0 ls -aldF > log.txt
echo "$founddata" | xargs -0 rm -rdf
find . -name "filename including space" -print0 |
xargs -0 -I '{}' sh -c 'ls -aldF {} >> log.txt; rm -rdf {}'
je crois que toutes ces réponses ont donné les bonnes façons de soluté ce problème. Et j'ai essayé les 2 solutions de Jonathan et la façon de faire de Glenn, qui ont toutes bien fonctionné sur mon Mac OS X. La méthode de mouvicien n'a pas fonctionné sur mon OS peut-être pour des raisons de configuration. Et je pense que C'est similaire à la deuxième méthode de Jonathan (je peux me tromper).
comme mentionné dans les commentaires à la méthode de Glenn, un petit ajustement est nécessaire. Donc, voici la commande que j'ai essayé qui a travaillé parfaitement pour info:
find . -name "filename including space" -print0 |
xargs -0 -I '{}' sh -c 'ls -aldF {} | tee -a log.txt ; rm -rdf {}'
Ou mieux, comme suggéré par Glenn:
find . -name "filename including space" -print0 |
xargs -0 -I '{}' sh -c 'ls -aldF {} >> log.txt ; rm -rdf {}'
tant que vous n'avez pas newline dans vos noms de fichiers, vous n'avez pas besoin de-print0 pour GNU Parallel:
find . -name "My brother's 12\" records" | parallel ls {}\; rm -rdf {} >log.txt
regardez la vidéo d'introduction pour en savoir plus:http://www.youtube.com/watch?v=OpaiGYxkSuQ
Juste une variation de l' xargs
approche sans l'horrible -print0
et xargs -0
, c'est la façon dont je le ferais:
ls -1 *.txt | xargs --delimiter "\n" --max-args 1 --replace={} sh -c 'cat {}; echo "\n"'
Notes de bas de page:
- Oui je sais que les retours à la ligne peuvent apparaître dans les noms de fichiers, mais qui dans leur bon esprit ferait que
- il y a de courtes options pour
xargs
mais pour comprendre le lecteur, j'ai utilisé les longues. - je voudrais utiliser
ls -1
quand je veux un comportement non récursif plutôt quefind -maxdepth 1 -iname "*.txt"
qui est un peu plus verbeux.
Vous pouvez exécuter plusieurs commandes après find
en utilisant for
au lieu de xargs
:
IFS=$'\n'
for F in `find . -name "filename including space"`
do
ls -aldF $F > log.txt
rm -rdf $F
done
IFS
définit le séparateur de champ interne, qui est par défaut
je suis en retard à la fête, mais il y a une solution de plus qui n'était pas couverte ici: des fonctions définies par l'utilisateur. Mettre plusieurs instructions sur une même ligne est lourd, et peut être difficile à lire/maintenir. Pour la boucle ci-dessus évite, mais il y a la possibilité de dépasser la ligne de commande de longueur.
Voici une autre façon (non testé).
function processFiles {
ls -aldF "$@"
rm -rdf "$@"
}
export -f processFiles
find . -name "filename including space"` -print0 \
| xargs -0 bash -c processFiles dummyArg > log.txt
C'est assez simple, sauf pour le "dummyArg" qui m'a donné beaucoup de chagrin. En tournant bash de cette façon, les arguments sont lus dans
"" "" "" ....
au lieu des
"" "" "" ....
Depuis processFiles{} sattend à ce que le premier argument "1$", nous avons pour insérer une valeur factice dans "0$".
Footnontes:
- j'utilise certains éléments de la syntaxe de bash (par exemple" export-F"), mais je crois que ça va s'adapter à d'autres coquilles.
- la première fois que j'ai essayé cela, je n'ai pas ajouté un mannequin argument. Au lieu de cela, j'ai ajouté"0$ " aux lignes d'argument à l'intérieur de ma fonction (par exemple ls-aldf "$0" "$@"). Mauvaise idée. Outre les questions de style, il se brise lorsque le "trouver" commande ne retourne rien. Dans ce cas, $0 est défini à "bash", en utilisant l'argument fictif évite tout cela.
une autre solution:
find . -name "filename including space" -print0 \
| xargs -0 -I FOUND echo "$(ls -aldF FOUND > log.txt ; rm -rdf FOUND)"