Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I know I can use seq to generate a random list of numbers 1, 2, 3, 4...

I want to get those numbers into a random order like 3, 1, 4, 2...

I know I can use shuf to shuffle the lines of a file. So I could use seq to write random numbers to a file and then use shuf to shuffle them -- or write some sort of shuffle function. But this seems needlessly complex. Is there a simpler way to randomize the items in an array with a single command?

share|improve this question

4 Answers 4

up vote 7 down vote accepted

You can just pipe the output to shuf.

$ seq 100 | shuf

Example

$ seq 10 | shuf
2
6
4
8
1
3
10
7
9
5

If you want the output to be horizontal then pipe it to paste.

$ seq 10 | shuf | paste - -s -d ' '
1 6 9 3 8 4 10 7 2 5 

$ seq 10 | shuf | paste - -s -d ' '
7 4 6 1 8 3 10 5 9 2 

$ seq 10 | shuf | paste - -s -d ' '
9 8 3 6 1 2 10 4 7 5 

Want it with commas in between? Change the delimiter to paste:

$ seq 10 | shuf | paste - -s -d ','
2,4,9,1,8,7,3,5,10,6
share|improve this answer
    
But you've gotta format somehow to get 'em on one line with commas. echo $(seq 10 | shuf) comes close but doesn't do the commas. –  mikeserv Apr 13 at 3:35
    
It's horizontal before paste ... –  mikeserv Apr 13 at 3:46
    
@mikeserv - changed it around. –  slm Apr 13 at 3:46
    
Yeah. There you go. I didnt know paste did that. Thanks for teaching me. Have an upvote. –  mikeserv Apr 13 at 3:47
    
@mikeserv - yeah read through the site looking at either mine, Stephane's or Gilles A's using join and paste. Those 2 tools are extremely powerful. –  slm Apr 13 at 3:48
printf '%s, ' `seq 1 10 | shuf`

You don't even need a for loop.

OUTPUT

7, 3, 4, 10, 2, 9, 1, 8, 5, 6,

To get them in a shell array you do:

( set -- $(seq 1 10 | shuf) ; printf '%s, ' "$@" )

OUTPUT

5, 9, 7, 2, 4, 3, 6, 1, 10, 8,

And then they're in your shell array.

If you get them in the shell array, you don't even need printf:

( set -- $(seq 1 10 | shuf); IFS=, ; echo "$*" )

OUTPUT

9,4,10,3,1,2,7,5,6,8

By the way, seq and printf are kinda made for each other. For instance if I want to repeat a string 1000 times?

printf 'a string\n%.0b' `seq 1 1000`

OUTPUT

a string

... 999 a string lines later...

a string

Or...

printf 'a string,%.0b' `seq 1 10`

OUTPUT

a string,a string,a string,a string,a string,a string,a string,a string,a string,a string,

I want to execute a command 39 times?

printf 'echo "run %d"\n' `seq 1 39` | . /dev/stdin

OUTPUT

run 1

... 38 run lines later ...

run 39
share|improve this answer

You may use shuf command to randomize output, e.g

%> for x in $(seq 1 10 | shuf); do echo -n "$x "; done; echo
4 10 8 7 1 6 3 5 2 9 
share|improve this answer

Is there a simpler way to randomize the items in an array with a single command?

Assuming you have an array:

arr=(4 8 14 18 24 29 32 37 42)

You could use printf and shuf to randomize the elements of the array:

$ arr=($(printf "%d\n" "${arr[@]}" | shuf))
$ echo "${arr[@]}"
4 37 32 14 24 8 29 42 18

If all that you need is random numbers between two integers, say 10 and 20, you do not need any extra processes other than shuf by using the -i option:

$ shuf -i 10-20
12
10
20
14
16
19
13
11
18
17
15

Quoting from man shuf:

   -i, --input-range=LO-HI
          treat each number LO through HI as an input line
share|improve this answer
    
Shucks. I saw that too in shuf --help but i tried to use shuf -i 1 10 without the intervening -dash. oh well, good work - have my upvote. –  mikeserv Apr 13 at 5:17

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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