15

This is probably dead easy, but is there a simple way to write a command once in the console, and have it executed n times, where n is specified at runtime? Something like this:

repeat 100 echo hello

Does such command exist (assume typical Linux installation)?

Or would I write to do some kind of loop in bash?

6 Answers 6

24

Yes this is possible. Bash has a very extensive scripting language. In this case:

for i in {1..100}; do echo 'hello'; done

More looping examples: http://www.cyberciti.biz/faq/bash-for-loop/
Full bash reference: http://www.gnu.org/software/bash/manual/bashref.html

3
  • what happens when the command fails ?
    – maazza
    May 10, 2013 at 8:22
  • Your error handling catches it and works out what to do instead.
    – Xyon
    Feb 4, 2014 at 13:39
  • I tried for i in {1..100}; do python3 foo.py ; done and actually mean to get the execution time (to see how fast) time for i in {1..100}; do python3 foo.py ; done and then CTRL-C won't be able to stop the loop Mar 8, 2020 at 15:36
5

The for loop syntax is silly. This is shorter:

seq 10|xargs -I INDEX echo "print this 10 times"
1
  • This is nice, but is there a way to bail out early if one of the commands fails?
    – jayarjo
    May 25, 2020 at 9:37
3

Or would I write to do some kind of loop in bash?

Yes, you would, like this:

for(( i = 0; i < 100; i++ )); do echo "hello"; done

or, shorter:

for((i=100;i--;)); do echo "hello"; done
1
  • and then put that stuff into a function and voila, you have your command: repeat() { for_stuff_here ; do "$@"; done }
    – akira
    Mar 22, 2010 at 15:03
3

In addition to more built in methods you could use an external utility that generates a sequence of numbers.

# gnu coreutils provides seq
for i in $(seq 1 100) ; do printf "hello\n" ; done

# freebsd (and probably other bsd) provides jot
for i in $(jot - 1 100) ; do printf "hello\n" ; done
3

I did not find a "standard" Linux tool to do this job, but I usually preserve my dot files (.bashrc, .vimrc etc.) from installation to installation, so the following is pretty "standard" if you look at it from the perspective of preserving your dot files in new installations:

At the end of your .bashrc or .bash_aliases, put the following definition:

repeat() {
  n=$1    #gets the number of times the succeeding command needs to be executed
  shift   #now $@ has the command that needs to be executed
  while [ $(( n -= 1 )) -ge 0 ]    #loop n times;
  do
    "$@"    #execute the command; you can also add error handling here or parallelize the commands
  done
}

Save the file and either reopen the shell or execute source /path/to/.bashrc or source /path/to/.bash_aliases, whichever you choose to modify, in an existing shell.

That's it! You should be able to use it in the following manner:

repeat 100 echo hello

repeat 84 ~/scripts/potato.sh

etc.

1
  • nice. it would be good to put "local" in front of the n=$1, to avoid polluting the global variable namespace
    – Don Hatch
    Dec 13, 2014 at 5:23
1

Currently, none of the other answers are using standard Unix tools which is what the title question is asking for.

They all use either non standard commands (seq or jot) or shell extensions (C-style for loop or brace expansion), i.e they all fail to stick with the POSIX standard.

Here is a portable way that should work with any POSIX compliant shell and operating system:

for i in $(awk 'BEGIN {for(i=0;i<100;i++) print i}'); do echo hello; done
1
  • First vote received 6 years after my reply, Yeah! 😃 👍
    – jlliagre
    Apr 14, 2020 at 17:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .