De vez en cuando ejecuto una línea de comando bash como esta:
n=0; while [[ $n -lt 10 ]]; do some_command; n=$((n+1)); done
Para ejecutar some_command
varias veces seguidas, 10 veces en este caso.
A menudo some_command
es realmente una cadena de comandos o una tubería.
¿Hay una manera más concisa de hacer esto?
let ++n
lugar den=$((n+1))
(3 caracteres menos).zsh
tienerepeat 10 do some_command; done
.sh: 1: [[: not found
.Respuestas:
O como una línea para aquellos que quieren copiar y pegar fácilmente:
fuente
for (n=0;n<k;n++))
puede ser mejor; Sospecho que{1..k}
se materializará una cadena con todos esos enteros separados por espacios.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
Usando una constante:
Usando una variable (puede incluir expresiones matemáticas):
fuente
x=10
for ((n=0; n < $x; n++));
for run in {1..10}; do echo "on run $run"; done
n
pasa si ya está configurado en un valor específico?for (( ; n<10; n++ ))
no funciona / editar: mejor utilizar probablemente una de las otras respuestas, como elwhile (( n++...
unoOtra forma simple de hackearlo:
ejecutar echo 20 veces.
Observe que eso
seq 20 | xargs -Iz echo "Hi there z"
generaría:fuente
seq 20
)seq 20 | xargs -I{} echo "Hi there {}"
z
no es un buen marcador de posición porque es tan común que puede ser un texto normal en el texto del comando. El uso{}
será mejor.seq
? así que solo se imprimiríaHi there
20 veces (sin número)? EDITAR: solo use-I{}
y luego no tenga ninguno{}
en el comandoIIIII
entonces se ve bien, por ejemplo:seq 20 | xargs -IIIIII timeout 10 yourCommandThatHangs
Si está utilizando el shell zsh:
Donde 10 es el número de veces que se repetirá el comando.
fuente
repeat 10 { !! }
Usando GNU Parallel puedes hacer:
Si no desea el número como argumento y solo ejecuta un trabajo a la vez:
Mire el video de introducción para una introducción rápida: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
Recorra el tutorial ( http://www.gnu.org/software/parallel/parallel_tutorial.html ). Usted ordena línea con amor por ello.
fuente
-j1 -N0
que a su vez fuera el paralelismo ????some_command
1000 veces en serie sin argumentos? Y: ¿Puedes expresar eso más corto queparallel -j1 -N0 some_command ::: {1..1000}
?repeat.sh repeatcount some_command
. Para la implementación en el script de shell que podría usarparallel
, si ya estuviera instalado en la máquina (probablemente no lo estaría). O podría gravitar hacia xargs ya que parece ser más rápido cuando no se necesita redireccionamientosome_command
.parallel -N0 -j1 --retries 4 --results outputdir/ some_command
Una función simple en el archivo de configuración bash (a
~/.bashrc
menudo) podría funcionar bien.Llámalo así.
fuente
do ${*:2}
, agregué evaldo eval ${*:2}
para asegurarme de que funcionaría para ejecutar comandos que no comienzan con ejecutables. Por ejemplo, si desea establecer una variable de entorno antes de ejecutar un comando comoSOME_ENV=test echo 'test'
.xargs
es rápido :En un moderno Linux de 64 bits, da:
Esto tiene sentido, ya que el
xargs
comando es un proceso nativo único que genera el/usr/bin/true
comando varias veces, en lugar de los buclesfor
ywhile
que se interpretan en Bash. Por supuesto, esto solo funciona para un solo comando; Si necesita hacer múltiples comandos en cada iteración del ciclo, será tan rápido, o tal vez más rápido, que pasarsh -c 'command1; command2; ...'
a xargsTambién
-P1
podría cambiarse, por ejemplo,-P8
para generar 8 procesos en paralelo para obtener otro gran impulso en la velocidad.No sé por qué GNU paralelo es tan lento. Pensé que sería comparable a los xargs.
fuente
Otra forma de tu ejemplo:
fuente
Por un lado, puede envolverlo en una función:
Llámalo como:
fuente
tr
aquí es engañoso y está trabajando en la salida demanytimes
, noecho
. Creo que deberías eliminarlo de la muestra.xargs y seq ayudarán
la vista :
fuente
Tenga en cuenta el guión bajo en lugar de usar una variable.
fuente
_
es un nombre variable.Si está bien haciéndolo periódicamente, puede ejecutar el siguiente comando para ejecutarlo cada 1 segundo indefinidamente. Puede colocar otras comprobaciones personalizadas para ejecutarlo n varias veces.
watch -n 1 some_command
Si desea tener una confirmación visual de los cambios, agregue
--differences
antes de lals
comando.Según la página del manual de OSX, también hay
La página de manual de Linux / Unix se puede encontrar aquí
fuente
Resolví con este bucle, donde repetir es un número entero que representa el número del bucle.
fuente
Otra respuesta más: use la expansión de parámetros en parámetros vacíos:
Probado en Centos 7 y MacOS.
fuente
Parece que todas las respuestas existentes requieren
bash
y no funcionan con un BSD UNIX estándar/bin/sh
(por ejemplo,ksh
en OpenBSD ).El siguiente código debería funcionar en cualquier BSD:
fuente
Un poco ingenuo, pero esto es lo que generalmente recuerdo de la cabeza:
Muy similar a la respuesta de @ joe-koberg. La suya es mejor, especialmente si necesita muchas repeticiones, pero es más difícil para mí recordar otra sintaxis porque en los últimos años no uso
bash
mucho. No me refiero a las secuencias de comandos al menos.fuente
El archivo de script
y la salida a continuación
fuente
¿Qué tal la forma alternativa de las construcciones de bucle
for
mencionadas (bashref) ?fuente
Los bucles son probablemente la forma correcta de hacerlo, pero aquí hay una alternativa divertida:
echo -e {1..10}"\n" |xargs -n1 some_command
Si necesita el número de iteración como parámetro para su invocación, use:
echo -e {1..10}"\n" |xargs -I@ echo now I am running iteration @
Editar: se comentó correctamente que la solución dada anteriormente funcionaría sin problemas solo con ejecuciones de comandos simples (sin tuberías, etc.). siempre puedes usar a
sh -c
para hacer cosas más complicadas, pero no vale la pena.Otro método que uso típicamente es la siguiente función:
rep() { s=$1;shift;e=$1;shift; for x in `seq $s $e`; do c=${@//@/$x};sh -c "$c"; done;}
ahora puedes llamarlo como:
rep 3 10 echo iteration @
Los primeros dos números dan el rango. El
@
será traducido al número de iteración. Ahora también puedes usar esto con tuberías:rep 1 10 "ls R@/|wc -l"
con darle el número de archivos en los directorios R1 .. R10.
fuente
rep 1 2 touch "foo @"
no creará dos archivos "foo 1" y "foo 2"; más bien crea tres archivos "foo", "1" y "2". Puede haber una manera de acertar con la cita usandoprintf
y%q
, pero será complicado obtener una secuencia arbitraria de palabras correctamente citadas en una sola cadena para pasarsh -c
.rep
en.bashrc
, las invocaciones adicionales se vuelven mucho más concisas.