有没有更好的方法在bash中运行命令N次?

时间:2010-09-17 17:56:26

标签: bash loops

我偶尔会运行这样的bash命令行:

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

连续多次运行some_command - 在这种情况下运行10次。

some_command通常是一系列命令或管道。

有更简洁的方法吗?

20 个答案:

答案 0 :(得分:382)

for run in {1..10}
do
  command
done

或者作为那些想要轻松复制和粘贴的人的单行代码:

for run in {1..10}; do command; done

答案 1 :(得分:192)

使用常数:

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

使用变量(可包括数学表达式):

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

答案 2 :(得分:109)

另一种破解它的简单方法:

seq 20 | xargs -Iz echo "Hi there"

运行回声20次。


请注意seq 20 | xargs -Iz echo "Hi there z"会输出:

  

你好1   你好2   ...

答案 3 :(得分:61)

如果你正在使用zsh shell:

repeat 10 { echo 'Hello' }

其中10是命令重复的次数。

答案 4 :(得分:23)

使用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)。你命令行 爱你吧。

答案 5 :(得分:14)

bash配置文件中的一个简单函数(经常为~/.bashrc)可以很好地工作。

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

这样称呼它。

$ runx 3 echo 'Hello world'
Hello world
Hello world
Hello world

答案 6 :(得分:10)

xargs

#!/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

这是有道理的,因为xargs命令是一个多次生成/usr/bin/true命令的单个本机进程,而不是所有forwhile循环用Bash解释。当然这仅适用于单个命令;如果你需要在循环的每次迭代中做多个命令,它将比将sh -c 'command1; command2; ...'传递给xargs

一样快,或者更快

-P1也可以更改为-P8,以并行生成8个进程,从而大大提高速度。

我不知道为什么GNU并行是如此之慢。我原以为它可以与xargs相媲美。

答案 7 :(得分:10)

您的示例的另一种形式:

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

答案 8 :(得分:7)

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

答案 9 :(得分:5)

for _ in {1..10}; do command; done   

注意下划线而不是使用变量。

答案 10 :(得分:5)

首先,你可以将它包装在一个函数中:

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

答案 11 :(得分:3)

如果您可以定期执行此操作,则可以运行以下命令以无限期每1秒运行一次。您可以使用其他自定义检查来运行它多次。

watch -n 1 some_command

如果您希望直观地确认更改,请在--differences命令之前附加ls

根据OSX手册页,还有

  

- 累积选项突出显示&#34;粘贴&#34;,呈现一个   运行显示所有已更改的位置。 -t   或--no-title选项关闭显示间隔的标题,   命令,以及显示屏顶部的当前时间,以及   以下空行。

可以找到Linux / Unix手册页here

答案 12 :(得分:2)

我用这个循环解决了,其中 repeat 是一个表示循环数的整数

repeat=10
for n in $(seq $repeat); 
    do
        command1
        command2
    done

答案 13 :(得分:1)

所有现有答案似乎都需要bash,并且不适用于标准BSD UNIX /bin/sh(例如ksh on OpenBSD)。

以下代码适用于任何BSD:

$ echo {1..4}
{1..4}
$ seq 4
sh: seq: not found
$ for i in $(jot 4); do echo e$i; done
e1
e2
e3
e4
$

答案 14 :(得分:1)

另一个答案:在空参数上使用参数扩展:

# calls curl 4 times 
curl -s -w "\n" -X GET "http:{,,,}//www.google.com"

在Centos 7和MacOS上测试过。

答案 15 :(得分:1)

有点天真,但这是我通常记得的头脑:

for i in 1 2 3; do
  some commands
done

非常类似于@ joe-koberg的回答。他更好,特别是如果你需要多次重复,我更难记住其他语法,因为在过去的几年里我并没有使用bash。我的意思是至少不要编写脚本。

答案 16 :(得分:1)

您可以使用此命令重复您的命令 10 次或更多次

for i in {1..10}; do **your command**; done

例如

for i in {1..10}; do **speedtest**; done

答案 17 :(得分:0)

For循环可能是正确的方法,但这是一个有趣的选择:

echo -e {1..10}"\n" |xargs -n1 some_command

如果需要迭代编号作为调用的参数,请使用:

echo -e {1..10}"\n" |xargs -I@ echo now I am running iteration @

编辑:正确评论说上面给出的解决方案只能通过简单的命令运行(没有管道等)顺利运行。你可以随时使用sh -c做更复杂的事情,但不值得。

我通常使用的另一种方法是以下功能:

rep() { s=$1;shift;e=$1;shift; for x in `seq $s $e`; do c=${@//@/$x};sh -c "$c"; done;}

现在您可以将其命名为:

rep 3 10 echo iteration @

前两个数字给出范围。 @将转换为迭代编号。现在你也可以用它来管道:

rep 1 10 "ls R@/|wc -l"

给你一个目录R1 .. R10中的文件数。

答案 18 :(得分:0)

(bashref)Looping Constructs中提到的for的替代形式怎么样?

答案 19 :(得分:0)

脚本文件

bash-3.2$ cat test.sh 
#!/bin/bash

echo "The argument is  arg: $1"

for ((n=0;n<$1;n++));
do
  echo "Hi"
done

和下面的输出

bash-3.2$  ./test.sh 3
The argument is  arg: 3
Hi
Hi
Hi
bash-3.2$