How can I repeat a character in Bash?

BashShellEcho

Bash Problem Overview


How could I do this with echo?

perl -E 'say "=" x 100'

Bash Solutions


Solution 1 - Bash

You can use:

printf '=%.0s' {1..100}

How this works:

Bash expands {1..100} so the command becomes:

printf '=%.0s' 1 2 3 4 ... 100

I've set printf's format to =%.0s which means that it will always print a single = no matter what argument it is given. Therefore it prints 100 =s.

Solution 2 - Bash

No easy way. But for example:

seq -s= 100|tr -d '[:digit:]'
# Editor's note: This requires BSD seq, and breaks with GNU seq (see comments)

Or maybe a standard-conforming way:

printf %100s |tr " " "="

There's also a tput rep, but as for my terminals at hand (xterm and linux) they don't seem to support it:)

Solution 3 - Bash

Tip of the hat to @gniourf_gniourf for his input.

Note: This answer does not answer the original question, but complements the existing, helpful answers by comparing performance.

Solutions are compared in terms of execution speed only - memory requirements are not taken into account (they vary across solutions and may matter with large repeat counts).

Summary:

  • If your repeat count is small, say up to around 100, it's worth going with the Bash-only solutions, as the startup cost of external utilities matters, especially Perl's.
    • Pragmatically speaking, however, if you only need one instance of repeating characters, all existing solutions may be fine.
  • With large repeat counts, use external utilities, as they'll be much faster.
    • In particular, avoid Bash's global substring replacement with large strings
      (e.g., ${var// /=}), as it is prohibitively slow.

The following are timings taken on a late-2012 iMac with a 3.2 GHz Intel Core i5 CPU and a Fusion Drive, running OSX 10.10.4 and bash 3.2.57, and are the average of 1000 runs.

The entries are:

  • listed in ascending order of execution duration (fastest first)
  • prefixed with:
    • M ... a potentially multi-character solution
    • S ... a single-character-only solution
    • P ... a POSIX-compliant solution
  • followed by a brief description of the solution
  • suffixed with the name of the author of the originating answer

  • Small repeat count: 100

[M, P] printf %.s= [dogbane]:                           0.0002
[M   ] printf + bash global substr. replacement [Tim]:  0.0005
[M   ] echo -n - brace expansion loop [eugene y]:       0.0007
[M   ] echo -n - arithmetic loop [Eliah Kagan]:         0.0013
[M   ] seq -f [Sam Salisbury]:                          0.0016
[M   ] jot -b [Stefan Ludwig]:                          0.0016
[M   ] awk - $(count+1)="=" [Steven Penny (variant)]:   0.0019
[M, P] awk - while loop [Steven Penny]:                 0.0019
[S   ] printf + tr [user332325]:                        0.0021
[S   ] head + tr [eugene y]:                            0.0021
[S, P] dd + tr [mklement0]:                             0.0021
[M   ] printf + sed [user332325 (comment)]:             0.0021
[M   ] mawk - $(count+1)="=" [Steven Penny (variant)]:  0.0025
[M, P] mawk - while loop [Steven Penny]:                0.0026
[M   ] gawk - $(count+1)="=" [Steven Penny (variant)]:  0.0028
[M, P] gawk - while loop [Steven Penny]:                0.0028
[M   ] yes + head + tr [Digital Trauma]:                0.0029
[M   ] Perl [sid_com]:                                  0.0059
  • The Bash-only solutions lead the pack - but only with a repeat count this small! (see below).
  • Startup cost of external utilities does matter here, especially Perl's. If you must call this in a loop - with small repetition counts in each iteration - avoid the multi-utility, awk, and perl solutions.

  • Large repeat count: 1000000 (1 million)

[M   ] Perl [sid_com]:                                  0.0067
[M   ] mawk - $(count+1)="=" [Steven Penny (variant)]:  0.0254
[M   ] gawk - $(count+1)="=" [Steven Penny (variant)]:  0.0599
[S   ] head + tr [eugene y]:                            0.1143
[S, P] dd + tr [mklement0]:                             0.1144
[S   ] printf + tr [user332325]:                        0.1164
[M, P] mawk - while loop [Steven Penny]:                0.1434
[M   ] seq -f [Sam Salisbury]:                          0.1452
[M   ] jot -b [Stefan Ludwig]:                          0.1690
[M   ] printf + sed [user332325 (comment)]:             0.1735
[M   ] yes + head + tr [Digital Trauma]:                0.1883
[M, P] gawk - while loop [Steven Penny]:                0.2493
[M   ] awk - $(count+1)="=" [Steven Penny (variant)]:   0.2614
[M, P] awk - while loop [Steven Penny]:                 0.3211
[M, P] printf %.s= [dogbane]:                           2.4565
[M   ] echo -n - brace expansion loop [eugene y]:       7.5877
[M   ] echo -n - arithmetic loop [Eliah Kagan]:         13.5426
[M   ] printf + bash global substr. replacement [Tim]:  n/a
  • The Perl solution from the question is by far the fastest.
  • Bash's global string-replacement (${foo// /=}) is inexplicably excruciatingly slow with large strings, and has been taken out of the running (took around 50 minutes(!) in Bash 4.3.30, and even longer in Bash 3.2.57 - I never waited for it to finish).
  • Bash loops are slow, and arithmetic loops ((( i= 0; ... ))) are slower than brace-expanded ones ({1..n}) - though arithmetic loops are more memory-efficient.
  • awk refers to BSD awk (as also found on OSX) - it's noticeably slower than gawk (GNU Awk) and especially mawk.
  • Note that with large counts and multi-char. strings, memory consumption can become a consideration - the approaches differ in that respect.

Here's the Bash script (testrepeat) that produced the above. It takes 2 arguments:

  • the character repeat count
  • optionally, the number of test runs to perform and to calculate the average timing from

In other words: the timings above were obtained with testrepeat 100 1000 and testrepeat 1000000 1000

#!/usr/bin/env bash

title() { printf '%s:\t' "$1"; }

TIMEFORMAT=$'%6Rs'

# The number of repetitions of the input chars. to produce
COUNT_REPETITIONS=${1?Arguments: <charRepeatCount> [<testRunCount>]}

# The number of test runs to perform to derive the average timing from.
COUNT_RUNS=${2:-1}

# Discard the (stdout) output generated by default.
# If you want to check the results, replace '/dev/null' on the following
# line with a prefix path to which a running index starting with 1 will
# be appended for each test run; e.g., outFilePrefix='outfile', which
# will produce outfile1, outfile2, ...
outFilePrefix=/dev/null

{

  outFile=$outFilePrefix
  ndx=0

  title '[M, P] printf %.s= [dogbane]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  # !! In order to use brace expansion with a variable, we must use `eval`.
  eval "
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    printf '%.s=' {1..$COUNT_REPETITIONS} >"$outFile"
  done"

  title '[M   ] echo -n - arithmetic loop [Eliah Kagan]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    for ((i=0; i<COUNT_REPETITIONS; ++i)); do echo -n =; done >"$outFile"
  done


  title '[M   ] echo -n - brace expansion loop [eugene y]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  # !! In order to use brace expansion with a variable, we must use `eval`.
  eval "
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    for i in {1..$COUNT_REPETITIONS}; do echo -n =; done >"$outFile"
  done
  "

  title '[M   ] printf + sed [user332325 (comment)]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    printf "%${COUNT_REPETITIONS}s" | sed 's/ /=/g' >"$outFile"
  done


  title '[S   ] printf + tr [user332325]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    printf "%${COUNT_REPETITIONS}s" | tr ' ' '='  >"$outFile"
  done


  title '[S   ] head + tr [eugene y]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    head -c $COUNT_REPETITIONS < /dev/zero | tr '\0' '=' >"$outFile"
  done


  title '[M   ] seq -f [Sam Salisbury]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    seq -f '=' -s '' $COUNT_REPETITIONS >"$outFile"
  done


  title '[M   ] jot -b [Stefan Ludwig]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    jot -s '' -b '=' $COUNT_REPETITIONS >"$outFile"
  done


  title '[M   ] yes + head + tr [Digital Trauma]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    yes = | head -$COUNT_REPETITIONS | tr -d '\n'  >"$outFile"
  done

  title '[M   ] Perl [sid_com]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    perl -e "print \"=\" x $COUNT_REPETITIONS" >"$outFile"
  done

  title '[S, P] dd + tr [mklement0]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    dd if=/dev/zero bs=$COUNT_REPETITIONS count=1 2>/dev/null | tr '\0' "=" >"$outFile"
  done

  # !! On OSX, awk is BSD awk, and mawk and gawk were installed later.
  # !! On Linux systems, awk may refer to either mawk or gawk.
  for awkBin in awk mawk gawk; do
    if [[ -x $(command -v $awkBin) ]]; then

      title "[M   ] $awkBin"' - $(count+1)="=" [Steven Penny (variant)]'
      [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
      time for (( n = 0; n < COUNT_RUNS; n++ )); do 
        $awkBin -v count=$COUNT_REPETITIONS 'BEGIN { OFS="="; $(count+1)=""; print }' >"$outFile"
      done

      title "[M, P] $awkBin"' - while loop [Steven Penny]'
      [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
      time for (( n = 0; n < COUNT_RUNS; n++ )); do 
        $awkBin -v count=$COUNT_REPETITIONS 'BEGIN { while (i++ < count) printf "=" }' >"$outFile"
      done

    fi
  done

  title '[M   ] printf + bash global substr. replacement [Tim]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  # !! In Bash 4.3.30 a single run with repeat count of 1 million took almost
  # !! 50 *minutes*(!) to complete; n Bash 3.2.57 it's seemingly even slower -
  # !! didn't wait for it to finish.
  # !! Thus, this test is skipped for counts that are likely to be much slower
  # !! than the other tests.
  skip=0
  [[ $BASH_VERSINFO -le 3 && COUNT_REPETITIONS -gt 1000 ]] && skip=1
  [[ $BASH_VERSINFO -eq 4 && COUNT_REPETITIONS -gt 10000 ]] && skip=1
  if (( skip )); then
    echo 'n/a' >&2
  else
    time for (( n = 0; n < COUNT_RUNS; n++ )); do 
      { printf -v t "%${COUNT_REPETITIONS}s" '='; printf %s "${t// /=}"; } >"$outFile"
    done
  fi
} 2>&1 | 
 sort -t$'\t' -k2,2n | 
   awk -F $'\t' -v count=$COUNT_RUNS '{ 
    printf "%s\t", $1; 
    if ($2 ~ "^n/a") { print $2 } else { printf "%.4f\n", $2 / count }}' |
     column -s$'\t' -t

Solution 4 - Bash

There's more than one way to do it.

Using a loop:

  • Brace expansion can be used with integer literals:

      for i in {1..100}; do echo -n =; done    
    
  • A C-like loop allows the use of variables:

      start=1
      end=100
      for ((i=$start; i<=$end; i++)); do echo -n =; done
    

Using the printf builtin:

printf '=%.0s' {1..100}

Specifying a precision here truncates the string to fit the specified width (0). As printf reuses the format string to consume all of the arguments, this simply prints "=" 100 times.

Using head (printf, etc) and tr:

head -c 100 < /dev/zero | tr '\0' '='
printf %100s | tr " " "="

Solution 5 - Bash

I've just found a seriously easy way to do this using seq:

UPDATE: This works on the BSD seq that comes with OS X. YMMV with other versions

seq  -f "#" -s '' 10

Will print '#' 10 times, like this:

##########
  • -f "#" sets the format string to ignore the numbers and just print # for each one.
  • -s '' sets the separator to an empty string to remove the newlines that seq inserts between each number
  • The spaces after -f and -s seem to be important.

EDIT: Here it is in a handy function...

repeat () {
    seq  -f $1 -s '' $2; echo
}

Which you can call like this...

repeat "#" 10

NOTE: If you're repeating # then the quotes are important!

Solution 6 - Bash

Here's two interesting ways:

ubuntu@ubuntu:~$ yes = | head -10 | paste -s -d '' -

ubuntu@ubuntu:$ yes = | head -10 | tr -d "\n" ==========ubuntu@ubuntu:$

Note these two are subtly different - The paste method ends in a new line. The tr method does not.

Solution 7 - Bash

There is no simple way. Avoid loops using printf and substitution.

str=$(printf "%40s")
echo ${str// /rep}
# echoes "rep" 40 times.

Solution 8 - Bash

The question was about how to do it with echo:

echo -e ''$_{1..100}'\b='

This will will do exactly the same as perl -E 'say "=" x 100' but with echo only.

Solution 9 - Bash

A pure Bash way with no eval, no subshells, no external tools, no brace expansions (i.e., you can have the number to repeat in a variable):

If you're given a variable n that expands to a (non-negative) number and a variable pattern, e.g.,

$ n=5
$ pattern=hello
$ printf -v output '%*s' "$n"
$ output=${output// /$pattern}
$ echo "$output"
hellohellohellohellohello

You can make a function with this:

repeat() {
    # $1=number of patterns to repeat
    # $2=pattern
    # $3=output variable name
    local tmp
    printf -v tmp '%*s' "$1"
    printf -v "$3" '%s' "${tmp// /$2}"
}

With this set:

$ repeat 5 hello output
$ echo "$output"
hellohellohellohellohello

For this little trick we're using printf quite a lot with:

  • -v varname: instead of printing to standard output, printf will put the content of the formatted string in variable varname.
  • '%*s': printf will use the argument to print the corresponding number of spaces. E.g., printf '%*s' 42 will print 42 spaces.
  • Finally, when we have the wanted number of spaces in our variable, we use a parameter expansion to replace all the spaces by our pattern: ${var// /$pattern} will expand to the expansion of var with all the spaces replaced by the expansion of $pattern.

You can also get rid of the tmp variable in the repeat function by using indirect expansion:

repeat() {
    # $1=number of patterns to repeat
    # $2=pattern
    # $3=output variable name
    printf -v "$3" '%*s' "$1"
    printf -v "$3" '%s' "${!3// /$2}"
}

Solution 10 - Bash

If you want POSIX-compliance and consistency across different implementations of echo and printf, and/or shells other than just bash:

seq(){ n=$1; while [ $n -le $2 ]; do echo $n; n=$((n+1)); done ;} # If you don't have it.

echo $(for each in $(seq 1 100); do printf "="; done)

...will produce the same output as perl -E 'say "=" x 100' just about everywhere.

Solution 11 - Bash

#!/usr/bin/awk -f
BEGIN {
  OFS = "="
  NF = 100
  print
}

Or

#!/usr/bin/awk -f
BEGIN {
  while (z++ < 100) printf "="
}

[Example][1] [1]:http://github.com/svnpenn/a/blob/9524a901324ab8535597/misc/reddit.sh#L20-L26

Solution 12 - Bash

Here's what I use to print a line of characters across the screen in linux (based on terminal/screen width)

printf '=%.0s' $(seq 1 $(tput cols))

Explanation:

Print an equal sign as many times as the given sequence:

printf '=%.0s' #sequence

Use the output of a command (this is a bash feature called Command Substitution):

$(example_command)

Give a sequence, I've used 1 to 20 as an example. In the final command the tput command is used instead of 20:

seq 1 20

Give the number of columns currently used in the terminal:

tput cols

Solution 13 - Bash

Another mean to repeat an arbitrary string n times:

Pros:

  • Works with POSIX shell.
  • Output can be assigned to a variable.
  • Repeats any string.
  • Very fast even with very large repeats.

Cons:

  • Requires Gnu Core Utils's yes command.
#!/usr/bin/sh
to_repeat='='
repeat_count=80
yes "$to_repeat" | tr -d '\n' | head -c "$repeat_count"

With an ANSI terminal and US-ASCII characters to repeat. You can use an ANSI CSI escape sequence. It is the fastest way to repeat a character.

#!/usr/bin/env bash

char='='
repeat_count=80
printf '%c\e[%db' "$char" "$repeat_count"

Or statically:

Print a line of 80 times =:

printf '=\e[80b\n'

Limitations:

  • Not all terminals understands the repeat_char ANSI CSI sequence.
  • Only US-ASCII or single-byte ISO characters can be repeated.
  • Repeat stops at last column, so you can use a large value to fill a whole line regardless of terminal width.
  • The repeat is only for display. Capturing output into a shell variable will not expand the repeat_char ANSI CSI sequence into the repeated character.

Solution 14 - Bash

In bash 3.0 or higher

for i in {1..100};do echo -n =;done

Solution 15 - Bash

I guess the original purpose of the question was to do this just with the shell's built-in commands. So for loops and printfs would be legitimate, while rep, perl, and also jot below would not. Still, the following command

jot -s "/" -b "\\" $((COLUMNS/2))

for instance, prints a window-wide line of \/\/\/\/\/\/\/\/\/\/\/\/

Solution 16 - Bash

As others have said, in bash brace expansion precedes parameter expansion, so {m,n} ranges can only contain literals. seq and jot provide clean solutions but aren't fully portable from one system to another, even if you're using the same shell on each. (Though seq is increasingly available; e.g., in FreeBSD 9.3 and higher.) eval and other forms of indirection always work but are somewhat inelegant.

Fortunately, bash supports C-style for loops (with arithmetic expressions only). So here's a concise "pure bash" way:

repecho() { for ((i=0; i<$1; ++i)); do echo -n "$2"; done; echo; }

This takes the number of repetitions as the first argument and the string to be repeated (which may be a single character, as in the problem description) as the second argument. repecho 7 b outputs bbbbbbb (terminated by a newline).

Dennis Williamson gave essentially this solution four years ago in his excellent answer to https://stackoverflow.com/questions/3211891/shell-script-create-string-of-repeated-characters. My function body differs slightly from the code there:

  • Since the focus here is on repeating a single character and the shell is bash, it's probably safe to use echo instead of printf. And I read the problem description in this question as expressing a preference to print with echo. The above function definition works in bash and ksh93. Although printf is more portable (and should usually be used for this sort of thing), echo's syntax is arguably more readable.

    Some shells' echo builtins interpret - by itself as an option--even though the usual meaning of -, to use stdin for input, is nonsensical for echo. zsh does this. And there definitely exist echos that don't recognize -n, as it is not standard. (Many Bourne-style shells don't accept C-style for loops at all, thus their echo behavior needn't be considered..)

  • Here the task is to print the sequence; there, it was to assign it to a variable.

If $n is the desired number of repetitions and you don't have to reuse it, and you want something even shorter:

while ((n--)); do echo -n "$s"; done; echo

n must be a variable--this way doesn't work with positional parameters. $s is the text to be repeated.

Solution 17 - Bash

Python is ubiquitous and works the same everywhere.

python -c "import sys; print('*' * int(sys.argv[1]))" "=" 100

Character and count are passed as separate parameters.

Solution 18 - Bash

repeat() {
    # $1=number of patterns to repeat
    # $2=pattern
    printf -v "TEMP" '%*s' "$1"
    echo ${TEMP// /$2}
}

Solution 19 - Bash

This is the longer version of what Eliah Kagan was espousing:

while [ $(( i-- )) -gt 0 ]; do echo -n "  "; done

Of course you can use printf for that as well, but not really to my liking:

printf "%$(( i*2 ))s"

This version is Dash compatible:

until [ $(( i=i-1 )) -lt 0 ]; do echo -n "  "; done

with i being the initial number.

Solution 20 - Bash

Simplest is to use this one-liner in csh/tcsh:

printf "%50s\n" '' | tr '[:blank:]' '[=]'

Solution 21 - Bash

A more elegant alternative to the proposed Python solution could be:

python -c 'print "="*(1000)'

Solution 22 - Bash

Another option is to use GNU seq and remove all numbers and newlines it generates:

seq -f'#%.0f' 100 | tr -d '\n0123456789'

This command prints the # character 100 times.

Solution 23 - Bash

Not to pile-on, but another pure-Bash approach takes advantage of ${//} substitution of arrays:

$ arr=({1..100})
$ printf '%s' "${arr[@]/*/=}"
====================================================================================================

Solution 24 - Bash

for i in {1..100}
do
  echo -n '='
done
echo

Solution 25 - Bash

In case that you want to repeat a character n times being n a VARIABLE number of times depending on, say, the length of a string you can do:

#!/bin/bash
vari='AB'
n=$(expr 10 - length $vari)
echo 'vari equals.............................: '$vari
echo 'Up to 10 positions I must fill with.....: '$n' equal signs'
echo $vari$(perl -E 'say "=" x '$n)

It displays:

vari equals.............................: AB  
Up to 10 positions I must fill with.....: 8 equal signs  
AB========  

Solution 26 - Bash

function repeatString()
{
    local -r string="${1}"
    local -r numberToRepeat="${2}"

    if [[ "${string}" != '' && "${numberToRepeat}" =~ ^[1-9][0-9]*$ ]]
    then
        local -r result="$(printf "%${numberToRepeat}s")"
        echo -e "${result// /${string}}"
    fi
}

Sample runs

$ repeatString 'a1' 10 
a1a1a1a1a1a1a1a1a1a1

$ repeatString 'a1' 0 

$ repeatString '' 10 

Reference lib at: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash

Solution 27 - Bash

> How could I do this with echo?

You can do this with echo if the echo is followed by sed:

echo | sed -r ':a s/^(.*)$/=\1/; /^={100}$/q; ba'

Actually, that echo is unnecessary there.

Solution 28 - Bash

My answer is a bit more complicated, and probably not perfect, but for those looking to output large numbers, I was able to do around 10 million in 3 seconds.

repeatString(){
	# argument 1: The string to print
	# argument 2: The number of times to print
	stringToPrint=$1
	length=$2

	# Find the largest integer value of x in 2^x=(number of times to repeat) using logarithms
	power=`echo "l(${length})/l(2)" | bc -l`
	power=`echo "scale=0; ${power}/1" | bc`

	# Get the difference between the length and 2^x
	diff=`echo "${length} - 2^${power}" | bc`

	# Double the string length to the power of x
	for i in `seq "${power}"`; do 
		stringToPrint="${stringToPrint}${stringToPrint}"
	done

	#Since we know that the string is now at least bigger than half the total, grab however many more we need and add it to the string.
	stringToPrint="${stringToPrint}${stringToPrint:0:${diff}}"
	echo ${stringToPrint}
}

Solution 29 - Bash

Simplest is to use this one-liner in bash:

seq 10 | xargs -n 1 | xargs -I {} echo -n  ===\>;echo

Solution 30 - Bash

Most existing solutions all depend on {1..10} syntax support of the shell, which is bash- and zsh- specific, and doesn't work in tcsh or OpenBSD's ksh and most non-bash sh.

The following should work on OS X and all *BSD systems in any shell; in fact, it can be used to generate a whole matrix of various types of decorative space:

$ printf '=%.0s' `jot 64` | fold -16
================
================
================
================$ 

Sadly, we don't get a trailing newline; which can be fixed by an extra printf '\n' after the fold:

$ printf "=%.0s" `jot 64` | fold -16 ; printf "\n"
================
================
================
================
$ 

References:

Solution 31 - Bash

My proposal (accepting variable values for n):

n=100
seq 1 $n | xargs -I {} printf =

Solution 32 - Bash

Slightly longer version, but if you have to use pure Bash for some reason, you can use a while loop with an incrementing variable:

n=0; while [ $n -lt 100 ]; do n=$((n+1)); echo -n '='; done

Solution 33 - Bash

Another bash solution using printf and tr

nb. before I begin:

  • Do we need another answer? Probably not.
  • Is this answer here already? Can't see it, so here goes.

Use the leading-zero-padding feature of printf and convert the zeroes using tr. This avoids any {1..N} generator:

$ printf '%040s' | tr '0' '='
========================================

To set the width to 'N' characters and customise the char printed:

#!/usr/bin/env bash
N=40
C='-'
printf "%0${N}s" | tr '0' "${C}"

For large N, this is quite a bit more performant than the generator; On my machine (bash 3.2.57):

$ time printf '=%.0s' {1..1000000}         real: 0m2.580s
$ time printf '%01000000s' | tr '0' '='    real: 0m0.577s

Solution 34 - Bash

n=5; chr='x'; chr_string='';
for (( i=0; $i<$n; i++ ))
do
	chr_string=$chr_string$chr
done
echo -n "$chr_string"

Works for...
n=integer (inclusive of zero and negetive).
chr=printable and white space (space and tab).

Solution 35 - Bash

printf -- '=%.0s' {1..100}

The double dash -- means "End of command line flags", so don't try to parse what comes after command line options.

If you want to print the dash - character, rather than the = character, multiple times and don't include the double dash -- this is what you'll get:

$ printf '-%.0s' {1..100}
bash: printf: -%: invalid option
printf: usage: printf [-v var] format [arguments]

Why not create a one line function like this:

function repeat() { num="${2:-100}"; printf -- "$1%.0s" $(seq 1 $num); }

Then, you can call it like this:

$ repeat -
----------------------------------------------------------------------------------------------------

or like that:

$ repeat =
====================================================================================================

or like this:

$ repeat '*' 8
********

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionsid_comView Question on Stackoverflow
Solution 1 - BashdogbaneView Answer on Stackoverflow
Solution 2 - Bashuser332325View Answer on Stackoverflow
Solution 3 - Bashmklement0View Answer on Stackoverflow
Solution 4 - BashEugene YarmashView Answer on Stackoverflow
Solution 5 - BashSam SalisburyView Answer on Stackoverflow
Solution 6 - BashDigital TraumaView Answer on Stackoverflow
Solution 7 - BashTimView Answer on Stackoverflow
Solution 8 - BashmanifestorView Answer on Stackoverflow
Solution 9 - Bashgniourf_gniourfView Answer on Stackoverflow
Solution 10 - BashGeoff NixonView Answer on Stackoverflow
Solution 11 - BashZomboView Answer on Stackoverflow
Solution 12 - Bashmattbell87View Answer on Stackoverflow
Solution 13 - BashLéa GrisView Answer on Stackoverflow
Solution 14 - BashloafoeView Answer on Stackoverflow
Solution 15 - BashStefan LudwigView Answer on Stackoverflow
Solution 16 - BashEliah KaganView Answer on Stackoverflow
Solution 17 - BashloevborgView Answer on Stackoverflow
Solution 18 - BashWSimpsonView Answer on Stackoverflow
Solution 19 - BashXennex81View Answer on Stackoverflow
Solution 20 - BashShawn GivlerView Answer on Stackoverflow
Solution 21 - BashAnas TiourView Answer on Stackoverflow
Solution 22 - BashsigalorView Answer on Stackoverflow
Solution 23 - Bashdimo414View Answer on Stackoverflow
Solution 24 - BashIgnacio Vazquez-AbramsView Answer on Stackoverflow
Solution 25 - BashRaul BaronView Answer on Stackoverflow
Solution 26 - BashNam NguyenView Answer on Stackoverflow
Solution 27 - BashDaBlerView Answer on Stackoverflow
Solution 28 - BashSilver OgreView Answer on Stackoverflow
Solution 29 - Bashshahin arefView Answer on Stackoverflow
Solution 30 - BashcnstView Answer on Stackoverflow
Solution 31 - BashSopalajo de ArrierezView Answer on Stackoverflow
Solution 32 - BashLuke MlsnaView Answer on Stackoverflow
Solution 33 - BashEd RandallView Answer on Stackoverflow
Solution 34 - BashNOYBView Answer on Stackoverflow
Solution 35 - Bashl3xView Answer on Stackoverflow