Есть ли лучший способ выполнить команду N раз в Bash? - PullRequest
257 голосов
/ 17 сентября 2010

Иногда я запускаю командную строку bash, например:

n=0; while [[ $n -lt 10 ]]; do some_command; n=$((n+1)); done

Для запуска some_command несколько раз подряд - в данном случае 10 раз.

Часто some_command - это действительно цепочка команд или конвейер.

Есть ли более лаконичный способ сделать это?

Ответы [ 19 ]

393 голосов
/ 17 сентября 2010
for run in {1..10}
do
  command
done

Или как однострочная для тех, кто хочет легко копировать и вставлять:

for run in {1..10}; do command; done
192 голосов
/ 17 сентября 2010

Использование константы:

for ((n=0;n<10;n++)); do some_command; done

Использование переменной (может включать математические выражения):

x=10 for ((n=0; n < (x / 2); n++)); do some_command; done
112 голосов
/ 19 ноября 2013

Другой простой способ взломать его:

seq 20 | xargs -Iz echo "Hi there"

выполнить эхо 20 раз.


Обратите внимание, что seq 20 | xargs -Iz echo "Hi there z" выведет:

Привет там 1
Привет там 2
...

63 голосов
/ 29 февраля 2016

Если вы используете оболочку zsh:

repeat 10 { echo 'Hello' }

Где 10 - количество повторений команды.

23 голосов
/ 18 января 2014

Используя GNU Parallel, вы можете сделать:

parallel some_command ::: {1..1000}

Если вы не хотите использовать число в качестве аргумента и запускать только одно задание за раз:

parallel -j1 -N0 some_command ::: {1..1000}

Смотреть вступлениевидео для быстрого ознакомления: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Пройдите учебник (http://www.gnu.org/software/parallel/parallel_tutorial.html). Командная строка, которую вы любите за это.

14 голосов
/ 08 июня 2015

Простая функция в файле конфигурации bash (~/.bashrc часто) может работать хорошо.

function runx() {
  for ((n=0;n<$1;n++))
    do ${*:2}
  done
}

Назовите это так.

$ runx 3 echo 'Hello world'
Hello world
Hello world
Hello world
10 голосов
/ 17 сентября 2010

Другая форма вашего примера:

n=0; while (( n++ < 10 )); do some_command; done
10 голосов
/ 05 апреля 2015

xargs is fast :

#!/usr/bin/bash
echo "while loop:"
n=0; time while (( n++ < 10000 )); do /usr/bin/true ; done

echo -e "\nfor loop:"
time for ((n=0;n<10000;n++)); do /usr/bin/true ; done

echo -e "\nseq,xargs:"
time seq 10000 | xargs -I{} -P1 -n1 /usr/bin/true

echo -e "\nyes,xargs:"
time yes x | head -n10000 |  xargs -I{} -P1 -n1 /usr/bin/true

echo -e "\nparallel:"
time parallel --will-cite -j1 -N0 /usr/bin/true ::: {1..10000}

В современном 64-битном Linux дает:

while loop:

real    0m2.282s
user    0m0.177s
sys     0m0.413s

for loop:

real    0m2.559s
user    0m0.393s
sys     0m0.500s

seq,xargs:

real    0m1.728s
user    0m0.013s
sys     0m0.217s

yes,xargs:

real    0m1.723s
user    0m0.013s
sys     0m0.223s

parallel:

real    0m26.271s
user    0m4.943s
sys     0m3.533s

Это имеет смысл, так как *Команда 1010 * - это отдельный собственный процесс, который запускает команду /usr/bin/true несколько раз вместо циклов for и while, которые все интерпретируются в Bash.Конечно, это работает только для одной команды;если вам нужно делать несколько команд в каждой итерации цикла, он будет таким же быстрым или, возможно, быстрее, чем передача sh -c 'command1; command2; ...' в xargs

-P1 также можно изменить, скажем, на -P8 для запуска 8 параллельных процессов, чтобы получить еще один большой прирост скорости.

Я не знаю, почему параллельная GNU такая медленная.Я бы подумал, что это будет сравнимо с xargs.

7 голосов
/ 22 августа 2011

xargs и seq помогут

function __run_times { seq 1 $1| { shift; xargs -i -- "$@"; } }

вид:

abon@abon:~$ __run_times 3  echo hello world
hello world
hello world
hello world
6 голосов
/ 17 сентября 2010

Например, вы можете заключить его в функцию:

function manytimes {
    n=0
    times=$1
    shift
    while [[ $n -lt $times ]]; do
        $@
        n=$((n+1))
    done
}

Назовите это как:

$ manytimes 3 echo "test" | tr 'e' 'E'
tEst
tEst
tEst
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...