Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I just discovered this useful bit of code on this useful-looking website.

 exec tclsh "$0" ${1+"$@"}

 proc main {} {
     set lines [lrange [split [read stdin] \n] 0 end-1]
     set count [llength $lines]

     for {set idx_1 0} {$idx_1 < $count} {incr idx_1} {
         set idx_2 [expr {int($count * rand())}]
         set temp [lindex $lines $idx_1]
         lset lines $idx_1 [lindex $lines $idx_2]
         lset lines $idx_2 $temp

     puts [join $lines \n]


Unfortunately, I don't like scripts. If I can, I make bash functions instead. (I've even gone so far as to completely obfuscate Python scripts in order to fit them into my ~/.bashrc unobtrusively, viz:)

dna-ify () {
python -c "exec'eJxdkUFrhDAQhe/5FdNsIQpu9rIspSBtLz330N4EiTq6AY0hiaW7v75j1F1aLwlv3vdmMu4eDpN3h0qbA5pvsJdwHg3bQT022nT51+f7/omx1o0DlGU7hclhWYIe7OgCWKdNINXUQRO1qsp1VjmPGfiLz6BSHk/HDNAsmZ6xWHaQ36zyzXXTgCZ8xEqSrhapmqZUay0Rre7RqAFFBoZUn4sXkbL5RlkrEY+Z8ZSi27mFlxv4zIA+H2jujpDRokn+GFLpUDVEYk+sGcP8BukDDS61VyFckvRfyN1wQ/3aaBsprumMvaUqu97JeJFxMZiIa68res61uhmW1cnqdFw9K0spMRMSvvww2NdQcPzBuhA8gy0iA14I2WBkC7HEFSK9S3NPEgoOj68EerQ55yn7BbL1snM='.decode('base64').decode('zlib')" $@

So, is there any (and, as the above sample should indicate, I do mean any) way I can do that with this bit of code?

share|improve this question
i think you need to get over your script-phobia. maybe stare at a #! line or a ~/bin/ directory listing until it doesn't fill you with revulsion..that kind of desensitisation sometimes works for other phobias. – cas Sep 9 '12 at 1:05
as long as it fits in my ~/.bashrc, craig sanders, i can take it with me wherever i go with minimal hassle, and become king of any console with a single mv command. – ixtmixilix Feb 24 '13 at 19:49
At most I think you need a function in your .bashrc script that grabs the latest copy of your script collection from your git repository or some such place, and installs it in ~/bin. – mc0e Jan 15 '15 at 13:58
up vote 2 down vote accepted

Tell tclsh to read the script from a different file descriptor, and use a here document to pass the script.

shuffle () {
  tclsh /dev/fd/3 "$@" 3<<'EOF'
proc main {} {
share|improve this answer
that's the sort of magic i was hoping to start using regularly. thank you. – ixtmixilix Sep 10 '12 at 9:35

Not what you ask for but line randomization is already implemented in coreutils.

Either use shuf or sort -r.

Try for example:

echo {1..10} | tr ' ' '\n' | shuf

Example output:

share|improve this answer
that's a good point, and i have used shuf a lot since reading your answer. thanks. – ixtmixilix Feb 24 '13 at 20:37
Note that shuf can do quality random ordering with --random-source=/dev/random, while sort -r is random enough for most purposes, but cryptographically poor. – mc0e Jan 15 '15 at 14:05

Your Answer


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.