Question redirection d'argument xargs


Cela semble être un problème insignifiant, mais la solution m'échappe si prudemment.

Je veux effacer beaucoup de fichiers texte; fichiers journaux. Raison? Pour économiser de l'espace disque

Avec un fichier texte, c'est aussi trivial que echo '' > path/to/file.txt

Cependant, les fichiers sont nombreux. J'ai eu recours à find et xargs. Mais je ne sais pas comment me déplacer "redirection d'entrée".

j'ai essayé find . -name <regex> | xargs -I target echo '' > target et echo '' > { find . -name <regex> | xargs -I target target }; aucun n'a fonctionné

Je ne suis pas bien familiarisé avec les scripts shell. Toute aide est appréciée.

Merci.


4
2017-07-26 05:01


origine




Réponses:


Ce que vous avez fait dans vos deux exemples est de mettre le > où le actuel shell peut le voir, donc la redirection ne se fait qu'une fois, avant que les commandes find et xargs ne soient exécutées. C'est ton premier problème.

Votre deuxième problème est que si vous citez le > afin qu'il soit transmis à xargs, ça ne marchera toujours pas car xargs ne passe pas votre commande à travers un shell, sauf si vous le lui demandez.

Votre troisième problème est que si vous demandez à xargs d’utiliser un shell pour exécuter la commande, le shell fera la mauvaise chose si des noms de fichiers contiennent des caractères amusants. (Aussi xargs fait la mauvaise chose avec des personnages amusants, mais cela peut être corrigé avec -0.)

Parmi les autres problèmes qui ne vous intéressent pas encore, citons:

  • écho '' ne crée pas un fichier vide, mais un fichier contenant une nouvelle ligne.
  • la -name option prend un glob, pas une regex.
  • vous voudrez peut-être ajouter -type f juste au cas où des répertoires correspondent au glob.

Voici une version partiellement corrigée de la commande:

find . -name '*thisisaglob*' -type f -print0 |
xargs -0 -I target sh -c ': > target'

Cela corrige la plupart des problèmes que j'ai mentionnés. Reste le problème du shell qui interprète mal un nom de fichier contenant des métacaractères de shell. Pour résoudre ce problème, vous devez donner le nom de fichier au shell en tant que paramètre plutôt que dans le cadre du -c commander. Cela ressemblerait à ceci:

find . -name '*thisisaglob*' -type f -print0 |
xargs -0 -I target sh -c ': > "$1"' fnord target

Le "fnord" est un espace réservé. Il devient $0 dont nous n'avons pas besoin.

Maintenant que l'objectif de xargs et de la redirection est réuni en toute sécurité, je vais vous montrer comment atteindre votre objectif en n'utilisant ni l'un ni l'autre.

find . -name '*thisisaglob*' -type f -exec truncate -s 0 '{}' +

Cela nécessite la truncate commande, qui fait partie de GNU coreutils et non un utilitaire standard Unix, donc moins portable, mais beaucoup plus facile à lire, n'est-ce pas?


9
2017-07-26 05:29



Même si ce n'était pas la solution, c'est très instructif. Cependant, cela a fonctionné. Malheureusement, je ne peux que voter une fois. Merci!! - iGbanam


Bien que la réponse d'Alan Curry soit approfondie, précise et très bien informée, j'ai une question. Pourquoi voulez-vous que les fichiers continuent à exister, même vides?

Ma recommandation naturelle serait:

find . -name <glob> -print0 | xargs -0 rm

Si vous aviez besoin des fichiers pour une raison quelconque, vous pouvez effectuer une série de commandes:

find . -name <glob> -print0 | tee /tmp/filelist | xargs -0 rm
cat /tmp/filelist | xargs -0 touch

Si vous vouliez simplement compresser les fichiers (par exemple, s'il s'agissait principalement d'informations redondantes / répétitives, mais que vous vouliez économiser de l'espace et conservez les fichiers), vous pouvez essayer:

find . -name <glob> -print0 | xargs -0 tar -xzf /tmp/logfiles.tgz

2
2017-07-26 05:43



Ce sont des applications de rails. Je préférerais garder les fichiers pour que le framework sache où placer les logs. - iGbanam


Si vous avez GNU Parallel http://www.gnu.org/software/parallel/ installé, vous pouvez le faire:

find . -name '*thisisaglob*' -type f | parallel '>'

Vous pouvez installer GNU Parallel simplement en:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem

Regardez les vidéos d'introduction pour GNU Parallel pour en savoir plus: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1


0
2017-07-30 20:08