2017-08-26 5 views
2

Ce que je veux faire estComment utiliser la substitution dans xargs?

  1. trouver tous les fichiers avec .txt l'extension
  2. cp-les à .dat fichier

il pourrait faire comme ceci:

for f in `find . -type f -name "*.txt"`; do cp $f ${f%.txt}.dat; done 

Je veux Pour ce faire avec xargs, j'ai essayé ceci:

find . -type f -name "*.txt" | xargs -i cp {} ${{}%.txt}.dat 

je vais erreur comme ceci:

bad substitution 

A ce propos, j'ai ces questions:

  1. comment faire la substitution à juste titre? Je suis curieux de savoir que xargs va faire les choses en parallèle quand for loop faire les choses un par un?

Répondre

1
  1. Comment faire la substitution à juste titre?

Vous ne pouvez pas utiliser la substitution de la manière que vous essayez de le faire parce que {} n'est pas une variable bash (seule partie de xargs syntaxe), donc bash ne peut pas effectuer la substitution sur elle.

Une meilleure façon de ce serait de créer une commande complète de bash et de fournir comme argument et xargs (par exemple xargs -0 -i bash -c 'echo cp "$1" "${1%.txt}.dat"' - '{}' - cette façon, vous pouvez effectuer la substitution de bash).

  1. Je suis curieux de savoir que xargs vont faire des choses parallèles lorsque la boucle for faire les choses une par une?

Oui, la boucle for fera pense sequently mais xargs par défaut sera toujours. Cependant, vous pouvez utiliser -P option xargs pour paralléliser, de xargs pages de manuel:

-P max-procs, --max-procs=max-procs 
      Run up to max-procs processes at a time; the default is 1. If max-procs is 0, xargs will run as many processes as possible at a time. Use the -n option or the -L option 
      with -P; otherwise chances are that only one exec will be done. While xargs is running, you can send its process a 

le signal SIGUSR1 pour augmenter le nombre de commandes à exécuter simultanément ou un SIGUSR2 pour diminuer le nombre. Vous ne pouvez pas l'augmenter au-delà d'une limite définie par l'implémentation ( affichée avec --show-limits). Vous ne pouvez pas le réduire en dessous de 1. xargs ne termine jamais ses commandes; Lorsqu'on lui demande de diminuer, il attend simplement que plusieurs commandes se terminent avant d'en lancer une autre.

Please note that it is up to the called processes to properly manage parallel access to shared resources. For example, if 

plus d'un d'entre eux tente d'imprimer à stdout, le ouptut sera produit dans un ordre indéterminé (et très probablement mélangé) à moins que les processus collaborent à une façon d'éviter cela. L'utilisation d'un système de verrouillage est un moyen de prévenir de tels problèmes. En général, l'utilisation d'un système de verrouillage permet d'assurer une sortie correcte, mais les performances diminuent de . Si vous ne voulez pas tolérer la différence de performance , organisez simplement chaque processus pour produire un fichier de sortie distinct (ou utilisez des ressources distinctes ).

2

Vous pouvez utiliser:

find . -type f -name "*.txt" -print0 | 
xargs -0 -i bash -c 'echo cp "$1" "${1%.txt}.dat"' - '{}' 
0

Si vous n'êtes pas satisfait de la construction bash -c '...' -, vous pouvez utiliser à la place parallèle GNU:

find . -type f -name "*.txt" -print0 | parallel -0 cp {} {.}.dat 
0

xargs et d'autres outils ne sont pas aussi flexibles que Perl pour ce genre de choses.

~ ❱ find . | perl -lne '-f && ($old=$_) && s/\.txt/.dat/g && print "$old => $_"' 
./dir/00.file.txt => ./dir/00.file.dat 
./dir/06.file.txt => ./dir/06.file.dat 
./dir/05.file.txt => ./dir/05.file.dat 
./dir/02.file.txt => ./dir/02.file.dat 
./dir/08.file.txt => ./dir/08.file.dat 
./dir/07.file.txt => ./dir/07.file.dat 
./dir/01.file.txt => ./dir/01.file.dat 
./dir/04.file.txt => ./dir/04.file.dat 
./dir/03.file.txt => ./dir/03.file.dat 
./dir/09.file.txt => ./dir/09.file.dat 

alors au lieu de print utiliser la fonction: rename $old, $_

Avec ce one-liner vous pouvez renommer ce que vous voulez


Pour forcer le xargs en mode parallèle, vous devez utiliser -P comme:

ls *.mp4 | xargs -I xxx -P 0 ffmpeg -i xxx xxx.mp3 

convertir tous les fichiers .mp4 en .mp3 en parallèle. Donc, si vous avez 10 mp4 alors 10 ffmpeg est en cours d'exécution simultanément.