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

bst*_*rre 273 bash loops

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

n=0; while [[ $n -lt 10 ]]; do some_command; n=$((n+1)); done
Run Code Online (Sandbox Code Playgroud)

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

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

有没有更简洁的方法来做到这一点?

Joe*_*erg 430

for run in {1..10}
do
  command
done
Run Code Online (Sandbox Code Playgroud)

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

for run in {1..10}; do command; done
Run Code Online (Sandbox Code Playgroud)

  • 如果你有很多迭代,那么`for(n = 0; n <k; n ++))`的形式可能会更好; 我怀疑`{1..k}`将实现一个字符串,其中所有那些整数用空格分隔. (19认同)
  • @bstpierre:大括号扩展形式不能使用变量(轻松)来指定Bash中的范围. (9认同)
  • 那是真实的.根据http://www.gnu.org/software/bash/manual/bashref.html#Brace-Expansion,在变量扩展之前执行大括号扩展,因此它永远不会看到任何变量的值. (5认同)
  • 可变扩张的悲伤之处.我正在使用以下循环n次并且已经格式化了数字:`n = 15;对于我在$(seq -f"%02g"$ {n}); do echo $ i; 完成01 02 03 04 05 06 07 08 09 10 11 12 13 14 15` (5认同)

Bat*_*hyX 198

使用常量:

for ((n=0;n<10;n++)); do some_command; done
Run Code Online (Sandbox Code Playgroud)

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

x=10 for ((n=0; n < (x / 2); n++)); do some_command; done
Run Code Online (Sandbox Code Playgroud)

  • 这是最接近编程语言的方法^^ - 应该是可以接受的! (4认同)
  • @Kunok在一行中运行已接受的答案也是可以接受的:`for run in {1..10}; 执行 echo "on run $run"; 完成` (2认同)

mit*_*tnk 115

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

seq 20 | xargs -Iz echo "Hi there"
Run Code Online (Sandbox Code Playgroud)

运行回声20次.


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

嗨那里有1
你好2
...

  • 2015版:`seq 20 | xargs -I {} echo"Hi there {}"` (14认同)
  • 请注意,`z`不是一个好的占位符,因为它很常见,可以是命令文本中的常规文本.使用`{}`会更好. (4认同)
  • 你甚至不需要1(可以只运行`seq 20`) (3认同)
  • 有什么方法可以丢弃`seq`中的数字?所以它只会打印'你好'20次(没有号码)?编辑:只需使用`-I {}`然后在命令中没有任何`{}` (3认同)

Wil*_*lva 70

如果您使用的是zsh shell:

repeat 10 { echo 'Hello' }
Run Code Online (Sandbox Code Playgroud)

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

  • 虽然它不是问题的答案(因为它明确提到了bash),但它非常有用并帮助我解决了我的问题.+1 (8认同)
  • 另外,如果您只是在终端中输入,则可以使用诸如repeat 10 {!! }` (2认同)
  • 有什么办法可以获取块中的运行号吗?例如 `{ echo "运行编号 $n" }` (2认同)

Ole*_*nge 25

使用GNU Parallel,您可以:

parallel some_command ::: {1..1000}
Run Code Online (Sandbox Code Playgroud)

如果您不希望将数字作为参数,并且一次只运行一个作业:

parallel -j1 -N0 some_command ::: {1..1000}
Run Code Online (Sandbox Code Playgroud)

观看介绍视频以获得快速介绍:https: //www.youtube.com/playlist?list = PL284C9FF2488BC6D1

浏览教程(http://www.gnu.org/software/parallel/parallel_tutorial.html).你命令行爱你.

  • 在这个具体情况下,它可能不是那么明显。如果您使用 GNU Parallel 的更多选项,例如,如果您想重试失败的命令 4 次并将输出保存到不同的文件: `parallel -N0 -j1 --retries 4 --results outputdir/ some_command` (2认同)

ste*_*eel 16

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

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

像这样称呼它.

$ runx 3 echo 'Hello world'
Hello world
Hello world
Hello world
Run Code Online (Sandbox Code Playgroud)

  • 这很完美。我唯一需要更改的是不只是执行`do $ {*:2}`,而是添加了eval`do eval $ {*:2}`,以确保它适用于运行不以开头的命令可执行文件。例如,如果您想在运行“ SOME_ENV = test echo'test'”之类的命令之前设置环境变量。 (2认同)

Pau*_*ce. 11

你的例子的另一种形式:

n=0; while (( n++ < 10 )); do some_command; done
Run Code Online (Sandbox Code Playgroud)


Jam*_*ven 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}
Run Code Online (Sandbox Code Playgroud)

在现代的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
Run Code Online (Sandbox Code Playgroud)

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

-P1也可以改变,比方说,-P8产卵并行8个流程,以获得速度的另一大助力.

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


Pan*_*hal 10

如果您可以定期执行此操作,则可以运行以下命令无限期地每 1 秒运行一次。您可以放置​​其他自定义检查以运行它 n 次。

watch -n 1 some_command

如果您希望对更改进行视觉确认,请--differencesls命令之前附加。

根据 OSX 手册页,还有

--cumulative 选项突出显示“粘性”,显示所有已更改位置的运行显示。-t 或 --no-title 选项关闭在显示屏顶部显示间隔、命令和当前时间的标题,以及后面的空行。

可以在此处找到 Linux/Unix 手册页


小智 7

xargs和seq会有所帮助

function __run_times { seq 1 $1| { shift; xargs -i -- "$@"; } }
Run Code Online (Sandbox Code Playgroud)

风景 :

abon@abon:~$ __run_times 3  echo hello world
hello world
hello world
hello world
Run Code Online (Sandbox Code Playgroud)

  • 命令的移位和双击怎么办?"转变"真的有必要吗? (2认同)
  • 如果命令比没有重定向的简单命令更复杂,则不起作用. (2认同)

bta*_*bta 6

首先,您可以将其包装在一个函数中:

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

称之为:

$ manytimes 3 echo "test" | tr 'e' 'E'
tEst
tEst
tEst
Run Code Online (Sandbox Code Playgroud)

  • 如果要运行的命令比没有重定向的简单命令更复杂,这将不起作用. (2认同)
  • 这里的`tr`是误导性的,它正在输出`manytimes`,而不是'echo`.我认为你应该从样品中删除它. (2认同)

小智 5

for _ in {1..10}; do command; done   
Run Code Online (Sandbox Code Playgroud)

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

  • 虽然从技术上讲,`_`是一个变量名. (8认同)

cns*_*nst 5

所有现有的答案似乎都需要bash,并且不适用于标准 BSD UNIX /bin/sh(例如,ksh在 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
$
Run Code Online (Sandbox Code Playgroud)


小智 5

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

repeat=10
for n in $(seq $repeat); 
    do
        command1
        command2
    done
Run Code Online (Sandbox Code Playgroud)


小智 5

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

for i in {1..10}; do **your command**; done
Run Code Online (Sandbox Code Playgroud)

例如

for i in {1..10}; do **speedtest**; done
Run Code Online (Sandbox Code Playgroud)