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.

24
demandé sur glenn jackman 2011-09-19 18:58:54

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
16
répondu Jonathan M 2014-08-05 08:08:39
find . -name "filename including space" -print0 | 
  xargs -0 -I '{}' sh -c 'ls -aldF {} >> log.txt; rm -rdf {}'
48
répondu glenn jackman 2012-11-16 22:53:50

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 {}'
5
répondu Richard Chen 2011-09-20 01:42:28

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

4
répondu Ole Tange 2011-09-20 17:06:37

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 que find -maxdepth 1 -iname "*.txt" qui est un peu plus verbeux.
2
répondu Sridhar-Sarnobat 2015-10-14 20:20:48

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 . Si vos noms de fichiers peuvent contenir des espaces, il est préférable de le redéfinir comme ci-dessus.

1
répondu ericbn 2014-07-20 15:36:03

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:

  1. 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.
  2. 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.
1
répondu Phil Freed 2016-03-27 02:37:29

une autre solution:

find . -name "filename including space" -print0 \
| xargs -0 -I FOUND echo "$(ls -aldF FOUND > log.txt ; rm -rdf FOUND)"
0
répondu mouviciel 2011-09-19 15:50:41