代码之家  ›  专栏  ›  技术社区  ›  bstpierre Edgar Aviles

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

  •  251
  • bstpierre Edgar Aviles  · 技术社区  · 14 年前

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

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

    some_command 连续几次——在本例中是10次。

    经常 一些命令 实际上是一个命令链或管道。

    有没有更简洁的方法?

    19 回复  |  直到 6 年前
        1
  •  528
  •   Toby Speight    3 年前

    如果你的范围有一个变量, use seq ,如下所示:

        count=10
        for i in $(seq $count); do
            command
        done
    

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

        for run in {1..10}; do command; done
    
        2
  •  210
  •   Nam G VU    4 年前

    使用常量:

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

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

    x=10; for ((n=0; n < (x / 2); n++)); do some_command; done
    
        3
  •  128
  •   Peter Neyens    9 年前

    seq 20 | xargs -Iz echo "Hi there"
    

    运行echo 20次。


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

    你好,1

    ...

        4
  •  87
  •   Wilson Silva    8 年前

    如果您使用的是zsh shell:

    repeat 10 { echo 'Hello' }
    

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

        5
  •  28
  •   Ole Tange    11 年前

    使用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 ). 你的命令行 因为我爱你。

        6
  •  20
  •   steel    6 年前

    bash配置文件中的一个简单函数( ~/.bashrc

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

    就这样说吧。

    $ runx 3 echo 'Hello world'
    Hello world
    Hello world
    Hello world
    
        7
  •  12
  •   James Scriven    9 年前

    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
    

    这是有道理的,因为 命令是生成 /usr/bin/true 多次命令,而不是 for while 所有在Bash中解释的循环。当然,这只适用于单个命令;如果您需要在循环的每个迭代中执行多个命令,那么它将与传递命令一样快,或者可能更快 sh -c 'command1; command2; ...'

    -P1 也可以改成, -P8 并行生成8个进程以获得速度上的另一个大提升。

    我不知道为什么GNU并行是如此缓慢。我本以为它可以和xargs相提并论。

        8
  •  11
  •   Dennis Williamson    14 年前

    你的例子的另一种形式:

    n=0; while (( n++ < 10 )); do some_command; done
    
        9
  •  9
  •   Pankaj Singhal    8 年前

    watch -n 1 some_command

    --differences ls 命令。

    根据OSX手册页,还有

    --cumulative选项使高亮显示变得“粘滞”,呈现 所有已更改位置的运行显示。t型 命令和显示顶部的当前时间,以及 在空行之后。

    可以找到Linux/Unix手册页 here

        10
  •  7
  •   bta    14 年前

    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
  •  7
  •   Gilles 'SO- stop being evil'    12 年前

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

    视图:

    abon@abon:~$ __run_times 3  echo hello world
    hello world
    hello world
    hello world
    
        12
  •  7
  •   gniourf_gniourf    10 年前
    for _ in {1..10}; do command; done   
    

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

        13
  •  5
  •   fvlgnn    7 年前

    是表示循环数的整数

    repeat=10
    for n in $(seq $repeat); 
        do
            command1
            command2
        done
    
        14
  •  4
  •   cnst    8 年前

    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
    $
    
        15
  •  4
  •   jcollum    8 年前

    另一个答案是:对空参数使用参数展开:

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

    在Centos 7和MacOS上测试。

        16
  •  2
  •   akostadinov    7 年前

    for i in 1 2 3; do
      some commands
    done
    

    bash 很多。我的意思是至少对脚本来说不是。

        17
  •  1
  •   stacksia    11 年前

    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
  •  1
  •   upog    7 年前

    脚本文件

    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$
    
        19
  •  1
  •   Martin Brisiak Abhiram Rajeevan    4 年前

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

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

    例如

    for i in {1..10}; do **speedtest**; done
    
        20
  •  0
  •   SamB som-snytt    14 年前

    另一种形式呢 for (bashref)Looping Constructs ?