J'exécute parfois une ligne de commande bash comme celle-ci:
n=0; while [[ $n -lt 10 ]]; do some_command; n=$((n+1)); done
Pour exécuter some_command
plusieurs fois de suite - 10 fois dans ce cas.
Il some_command
s'agit souvent d' une chaîne de commandes ou d'un pipeline.
Existe-t-il une manière plus concise de procéder?
let ++n
place den=$((n+1))
(3 caractères de moins).zsh
ouirepeat 10 do some_command; done
.sh: 1: [[: not found
.Réponses:
Ou comme une ligne pour ceux qui veulent copier et coller facilement:
la source
for (n=0;n<k;n++))
peut être meilleur; Je suspecte de{1..k}
matérialiser une chaîne avec tous ces entiers séparés par des espaces.n=15;for i in $(seq -f "%02g" ${n});do echo $i; done 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
En utilisant une constante:
Utilisation d'une variable (peut inclure des expressions mathématiques):
la source
x=10
for ((n=0; n < $x; n++));
for run in {1..10}; do echo "on run $run"; done
n
est déjà défini sur une valeur spécifique?for (( ; n<10; n++ ))
ne fonctionne pas / ne modifie pas: il est préférable d'utiliser l'une des autres réponses comme celle-while (( n++...
làUn autre moyen simple de le pirater:
exécuter l'écho 20 fois.
Notez que cela
seq 20 | xargs -Iz echo "Hi there z"
produirait:la source
seq 20
)seq 20 | xargs -I{} echo "Hi there {}"
z
n'est pas un bon espace réservé car il est si courant qu'il peut s'agir d'un texte normal dans le texte de la commande. L'utilisation{}
sera meilleure.seq
? il imprimerait doncHi there
20 fois (pas de numéro)? EDIT: utilisez simplement-I{}
et n'en avez pas{}
dans la commandeIIIII
alors il a l'air bien par exemple:seq 20 | xargs -IIIIII timeout 10 yourCommandThatHangs
Si vous utilisez le shell zsh:
Où 10 est le nombre de fois que la commande sera répétée.
la source
repeat 10 { !! }
En utilisant GNU Parallel, vous pouvez faire:
Si vous ne voulez pas le nombre comme argument et que vous n'exécutez qu'un seul travail à la fois:
Regardez la vidéo d'introduction pour une introduction rapide: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
Parcourez le didacticiel ( http://www.gnu.org/software/parallel/parallel_tutorial.html ). Vous commandez en ligne avec amour pour vous.
la source
-j1 -N0
qui désactivent le parallélisme ????some_command
1000 fois en série sans argument? Et: Pouvez-vous exprimer cela plus court queparallel -j1 -N0 some_command ::: {1..1000}
?repeat.sh repeatcount some_command
. Pour la mise en œuvre dans le script shell, je pourrais utiliserparallel
, s'il était déjà installé sur la machine (ce ne serait probablement pas le cas). Ou je pourrais graviter vers xargs car cela semble être le plus rapide lorsqu'aucune redirection n'est nécessaire parsome_command
.parallel -N0 -j1 --retries 4 --results outputdir/ some_command
Une fonction simple dans le fichier de configuration bash (
~/.bashrc
souvent) pourrait bien fonctionner.Appelez ça comme ça.
la source
do ${*:2}
j'ai ajouté evaldo eval ${*:2}
pour m'assurer qu'il fonctionnerait pour l'exécution de commandes qui ne commencent pas par des exécutables. Par exemple, si vous souhaitez définir une variable d'environnement avant d'exécuter une commande commeSOME_ENV=test echo 'test'
.xargs
est rapide :Sur un Linux 64 bits moderne, donne:
Cela a du sens, car la
xargs
commande est un processus natif unique qui génère la/usr/bin/true
commande plusieurs fois, au lieu des bouclesfor
etwhile
qui sont toutes interprétées dans Bash. Bien sûr, cela ne fonctionne que pour une seule commande; si vous avez besoin de faire plusieurs commandes à chaque itération de la boucle, ce sera tout aussi rapide, ou peut-être plus rapide, que de passersh -c 'command1; command2; ...'
à xargsLe
-P1
pourrait également être modifié pour, par exemple,-P8
engendrer 8 processus en parallèle pour obtenir un autre coup de pouce de vitesse.Je ne sais pas pourquoi le parallèle GNU est si lent. J'aurais pensé que ce serait comparable aux xargs.
la source
Une autre forme de votre exemple:
la source
D'une part, vous pouvez le résumer dans une fonction:
Appelez ça comme:
la source
tr
ici est trompeur et il fonctionne sur la sortie demanytimes
, nonecho
. Je pense que vous devriez le retirer de l'échantillon.xargs et seq aideront
la vue :
la source
Notez le trait de soulignement au lieu d'utiliser une variable.
la source
_
c'est un nom de variable.Si vous êtes d'accord pour le faire périodiquement, vous pouvez exécuter la commande suivante pour l'exécuter toutes les 1 s indéfiniment. Vous pouvez mettre en place d'autres contrôles personnalisés pour l'exécuter n nombre de fois.
watch -n 1 some_command
Si vous souhaitez avoir une confirmation visuelle des modifications, ajoutez-les
--differences
avant lals
commande.Selon la page de manuel OSX, il y a aussi
La page de manuel Linux / Unix peut être trouvée ici
la source
J'ai résolu avec cette boucle, où la répétition est un entier qui représente le nombre de boucles
la source
Encore une autre réponse: utilisez l'expansion des paramètres sur les paramètres vides:
Testé sur Centos 7 et MacOS.
la source
Toutes les réponses existantes semblent nécessiter
bash
et ne fonctionnent pas avec un BSD UNIX standard/bin/sh
(par exemple,ksh
sur OpenBSD ).Le code ci-dessous devrait fonctionner sur n'importe quel BSD:
la source
Un peu naïf mais c'est ce dont je me souviens habituellement du haut de ma tête:
Très similaire à la réponse de @ joe-koberg. La sienne est meilleure, surtout si vous avez besoin de nombreuses répétitions, juste plus difficile pour moi de me souvenir d'une autre syntaxe car ces dernières années, je n'utilise pas
bash
beaucoup. Je veux dire pas pour les scripts au moins.la source
Le fichier script
et la sortie ci-dessous
la source
Que diriez - vous de la forme alternative de
for
mentionné dans (bashref) Looping Constructs ?la source
Les boucles sont probablement la bonne façon de le faire, mais voici une alternative amusante:
echo -e {1..10}"\n" |xargs -n1 some_command
Si vous avez besoin du numéro d'itération comme paramètre pour votre appel, utilisez:
echo -e {1..10}"\n" |xargs -I@ echo now I am running iteration @
Edit: Il a été à juste titre commenté que la solution donnée ci-dessus ne fonctionnerait correctement qu'avec des exécutions de commandes simples (pas de tuyaux, etc.). vous pouvez toujours utiliser un
sh -c
pour faire des choses plus compliquées, mais cela n'en vaut pas la peine.Une autre méthode que j'utilise généralement est la fonction suivante:
rep() { s=$1;shift;e=$1;shift; for x in `seq $s $e`; do c=${@//@/$x};sh -c "$c"; done;}
vous pouvez maintenant l'appeler comme:
rep 3 10 echo iteration @
Les deux premiers chiffres donnent la plage. Le
@
sera traduit au numéro d'itération. Maintenant, vous pouvez également l'utiliser avec des tuyaux:rep 1 10 "ls R@/|wc -l"
vous donne le nombre de fichiers dans les répertoires R1 .. R10.
la source
rep 1 2 touch "foo @"
ne crée pas deux fichiers "foo 1" et "foo 2"; il crée plutôt trois fichiers "foo", "1" et "2". Il peut y avoir un moyen d'obtenir la bonne citation en utilisantprintf
et%q
, mais il va être difficile d'obtenir une séquence arbitraire de mots correctement cités dans une seule chaîne pour passersh -c
.rep
dans votre.bashrc
, les appels ultérieurs deviennent beaucoup plus concis.