103

Is there any built-in Linux command that allows to output a string that is n times an input string??

3
  • 2
    By "built-in linux command" I assume you mean shell command, and since you don't mention which shell you're using, I assume it's bash. You can check this by typing "echo $SHELL" at the command line and you should get something similar to "/bin/bash" back. If you don't, you should edit your answer to specify what it does show. Cheers :) Dec 22, 2009 at 3:12
  • 8
    I tagged the question with "bash". I thought that would've been enough.
    – GetFree
    Dec 22, 2009 at 3:27
  • 1
    Related on Stack Overflow: stackoverflow.com/q/3211891/2157640
    – Palec
    Nov 16, 2014 at 14:33

16 Answers 16

112
adrian@Fourier:~$ printf 'HelloWorld\n%.0s' {1..5}
HelloWorld
HelloWorld
HelloWorld
HelloWorld
HelloWorld
adrian@Fourier:~$
9
  • 10
    Could you explain how this works? I understand the printf command since it's the same as the one in C/C++. But I dont understand how the {1..5} is expanded and how that works in conjunction with the "%.0s" part.
    – GetFree
    Dec 22, 2009 at 3:24
  • 8
    It's a bit of a hack :) Try running "printf 'HelloWorld %d\n' 1 2 3 4 5" and it'll probably click for you. The %.0s flag is meant to do nothing, just be there to pick up arguments. Then, if bash gets more arguments than it has format specifiers, it will simply print out multiple copies, grabbing as many as it needs. So you get the effect. The output of "printf 'HelloWorld %d%d\n' 1 2 3 4 5 6" probably makes it even clearer. Hope this helps! Dec 22, 2009 at 3:44
  • I see. It's the particular behavior of printf what allows the repetition
    – GetFree
    Dec 22, 2009 at 3:53
  • 1
    (I should note that, from a purely theoretical standpoint, this is probably the fastest solution since it uses a single shell primitive -- not any external processes. In reality though, let's face it, performance of bash scripts doesn't really matter :) Dec 22, 2009 at 3:53
  • 2
    What is specific to printf is that it will repeatedly apply excess arguments to the format string, "looping" for free. By "excess", I mean that there are more arguments than % placeholders. May 8, 2012 at 20:38
94

Here's an old-fashioned way that's pretty portable:

yes "HelloWorld" | head -n 10

This is a more conventional version of Adrian Petrescu's answer using brace expansion:

for i in {1..5}
do
    echo "HelloWorld"
done

That's equivalent to:

for i in 1 2 3 4 5

This is a little more concise and dynamic version of pike's answer:

printf -v spaces '%*s' 10 ''; printf '%s\n' ${spaces// /ten}
8
  • How do you get rid of the new lines when using the yes command?
    – GetFree
    Dec 22, 2009 at 4:16
  • 3
    One way is to pipe it through sed -n 'H;${x;s/\n//gp}' or sed -n ':t;${s/\n//gp};N;bt' another is to do echo $(yes "HelloWorld" | head -n 10) which adds a space between each copy of the string. Yet another way is to pipe it through tr -d '\n' which also eliminates the final newline. Dec 22, 2009 at 9:08
  • 2
    It's like Haskell in a bash shell: Hashell?
    – wchargin
    Jan 15, 2014 at 5:20
  • 6
    The yes solution is pretty neat
    – piggybox
    Jun 26, 2015 at 20:04
  • 1
    @arnsholt: OK, I would use a for loop instead of spawning an external executable (yes). Or capture it once and output it twice like: out=$(my-command); printf '%s\n' "$out" "$out" (printf will apply excess arguments sequentially) or other similar techniques. Aug 3, 2016 at 19:15
18

You can use a trick. Echoing an empty variable does not print anything. So you can write:

echo word$wojek{1..100}

If $wojek1 $wojek2 ... $wojek100 are non-existing variables you will get your word repeated 100 times without anything else.

3
  • 1
    It's an ugly ugly hack, and yet I can't help but love it and use it.
    – 16807
    Jul 14, 2017 at 17:38
  • 3
    Love it! Maybe using $_ instead of $wojek makes the intent clearer. Sep 4, 2019 at 14:13
  • Great trick. For those who care a little bit more about bash scripts' correctness this should be: set +u; echo word$wojek{1..100}; set -u assuming set -eu is set above.
    – macieksk
    Apr 24, 2021 at 12:33
17

Quite a few good ways already mentioned. Can't forget about good old seq though:

[john@awesome]$for i in `seq 5`; do echo "Hi";done
Hi
Hi
Hi
Hi
Hi
1
  • This one actually respects a zero, treating it as zero! (The {i..j} trick never returns an empty range.) Oct 15, 2016 at 2:48
17

This can be parameterized and doesn't require a temp variable, FWIW:

printf "%${N}s" | sed 's/ /blah/g'

Or, if $N is the size of a bash array:

echo ${ARR[@]/*/blah}
2
  • 3
    This is the shortest POSIX 7 solution I have seen so far since seq, yes and {1..5} are not POSIX 7. Apr 10, 2014 at 11:27
  • 2
    You shouldn't mix data into printf's format specifier. What if the data contains format strings? This is the correct way to dynamically specify the "precision" (length): printf '%*s' "$N" - make it a habit to enclose the format string in single quotes to prevent variable expansion there. Jan 5, 2019 at 14:22
11

Perhaps another way that is more general and useful for you:

adrian@Fourier:~$ n=5
adrian@Fourier:~$ for (( c=1; c<=n; c++)) ; do echo "HelloWorld" ; done
HelloWorld
HelloWorld
HelloWorld
HelloWorld
HelloWorld
adrian@Fourier:~$ 

The bash shell is more powerful than most people think :)

3
  • This gets my vote, as it's entirely shell-internal; no forking required.
    – esm
    Dec 23, 2009 at 18:08
  • 2
    What forking are you referring to? The original answer requires none. The output of 'type printf' is 'printf is a shell builtin' and therefore runs within the original bash process.
    – CodeGnome
    Apr 17, 2012 at 20:17
  • This is the only one so far (yes, printf, for i in {1..5}) that if the n is zero, it returns empty string without exist status of 1. Also due to the mathematical notation for comparison, it is easy to have offset by 1 (e.g by changing the <= to <) Jun 19, 2019 at 8:54
11

Repeat n times, just put n-1 commas between {}:

$ echo 'helloworld'{,,}
helloworld helloworld helloworld

Repeats 'helloworld' twice after the first echo.

4
  • 5
    Nice, but what if I want to get n from a variable?
    – GetFree
    Jun 28, 2012 at 7:32
  • 3
    it add an extra space after each 'helloworld'
    – PADYMKO
    Mar 7, 2017 at 11:28
  • this doesn't seem to let you put newlines in the string either (ie getting helloworld on their own lines) Feb 1, 2019 at 16:54
  • @GetFree: most solutions here use bash's {1..5} expansion, which also does not support parametrize from a variable
    – MestreLion
    Nov 22, 2021 at 11:10
6

I've experienced broken pipe warnings with the yes solution, so here's another good alternative:

$ seq 4 | sed "c foo"
foo
foo
foo
foo
6

POSIX AWK:

#!/usr/bin/awk -f
function str_repeat(s1, n1) {
   s2 = ""
   for (n2 = 1; n2 <= n1; n2++) {
      s2 = s2 s1
   }
   return s2
}
BEGIN {
   s3 = str_repeat("Sun", 5)
   print s3
}

Or PHP:

<?php
$s3 = str_repeat('Sun', 5);
echo $s3, "\n";
2
  • Use this without the awk: while (( c++ < 5 )); do printf 'hello'; done
    – emf
    Feb 21, 2017 at 8:33
  • POSIXly portable. I like this answer Jan 13, 2020 at 8:15
5

based on what @pike was hinting at

for every character in string echo string

echo ${target//?/$replace}

An example of a heading underlined with = characters

export heading='ABCDEF'; 
export replace='='; 
echo -e "${heading}\n${heading//?/$replace}"

will output

ABCDEF
======

This seems to port between linux and OS X and that makes me happy.

nJoy!

5

No magic here:

seq 5 | awk '{print "Hello World"}'

0
3

Assuming you want something like Perl's x operator, where you don't automatically get a newline between repetitions:

x() {
  # usage: x string num
  for i in $(seq 1 $2); do printf "%s" "$1"; done
  # print a newline only if the string does not end in a newline
  [[ "$1" == "${1%$'\n'}" ]] && echo ""
}

x Hi 10  # ==> HiHiHiHiHiHiHiHiHiHi

x $'Hello World!\n' 3

I explicitly used a for loop because you can't write {1..$n} in bash: brace expansion is done before variable substitution.

3

If you're on BSD, you can just use seq.

$ seq -f "Hello, world" 5
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
1
  • 3
    In seq (GNU coreutils) 8.25, this gives seq: format 'Hello, world' has no % directive, forcing a formatting directive to be present. GNU coreutils are used e.g. n many Linux distributions and Cygwin. Including the info here for those missing the info that it works only in BSD seq.
    – Palec
    Jun 19, 2017 at 10:08
2
line="==========================="
line=${line:0:10}
${line//"="/"ten "}

outputs

ten ten ten ten ten ten ten ten ten ten
1
  • 1
    Maybe a more verbose example: declare c='-----'; c=${c//${c:0:1}/$c}; echo $c # Prints "-" 25 times. Jan 2, 2013 at 23:02
2

Try this one:

echo $(for i in $(seq 1 100); do printf "-"; done)

Will create (a hundred dash):


1
  • I like this answer, as when "n" is an environment var (e.g. $n), the curly-brace syntax doesn't work: n=10 && echo {1..$n} produces {1..10}, whereas echo {1..3} produces 1 2 3. Oct 2, 2020 at 22:37
2

Not exactly built in to linux, but if you have python installed..

python
>>>var = "string"
>>>var*n

Or in one line, as commenter suggested:

python -c 'print "This is a test.\n" * 10'
4
  • 4
    Not really that useful, since it can't be easily integrated into shell scripts, etc. And since there's about a billion ways to do this in the shell itself, I see little reason to bring out the big guns (i.e Python) for it. Dec 22, 2009 at 3:18
  • 8
    I agree with your second point but not the fist...it's easy to integrate into a shell script: python -c 'print "This is a test.\n" * 10'
    – larsks
    Dec 22, 2009 at 14:26
  • 1
    I like the readability of this solution, good reason enough for me. ;)
    – elias
    Aug 16, 2015 at 20:28
  • @AdrianPetrescu this is hardly different from the other solutions that are using things like sed and awk except that it's more readable. Unless you're running it in a tight loop many times, the cost of starting the interpreter is negligible.
    – Z4-tier
    May 15 at 0:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.