#!/bin/bash : <<=cut =pod =head1 NAME rand - generate (pseudo-)random data =head1 SYNOPSIS B [-f FORMAT|--format FORMAT] [-s SEED|--seed SEED] [[I] I] =head1 DESCRIPTION B uses B to generate pseudorandom data. Just like B it generates an infinite amount of data, but it is much faster (400 MB/s on hardware from 2013). The quality is lower as there are only 2^256 different tables (this is still around the number of atoms in the visible universe). If I is given, numbers will be integers from 0 to I. If I is also given, numbers will be integers from I to I. =head1 OPTIONS =over 4 =item B<--format> I =item B<-f> I Format number using I. I follows Bs specification. =item B<--seed> I =item B<-s> I Use SEED for random number generator for reproducible numbers. =back =head1 EXAMPLE Overwrite a harddisk with random data: rand >/dev/sda =head1 EXAMPLE 100 random numbers from 1000 to 1999: rand 1000 1999 | head -n 100 =head1 EXAMPLE 100 random numbers from 256 to 65535 in hex with 0s prepended: rand -f '%04x\n' 256 65535 | head -n 100 =head1 AUTHOR Copyright (C) 2017-2020 Ole Tange, http://ole.tange.dk and Free Software Foundation, Inc. =head1 LICENSE Copyright (C) 2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or at your option any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . =head1 DEPENDENCIES B uses B, B, and B. =head1 SEE ALSO B =cut randdata() { # Generate random 8-bit data by AES encrypting /dev/zero if [ "$seed" == "" ] ; then # use a random key key=$(openssl rand -hex 16) iv=$(openssl rand -hex 16) else # use seed from --seed key=$(echo "$seed" | openssl sha256 -hex | cut -d' ' -f2) iv=$(echo "$seed" | openssl sha512 -hex | cut -d' ' -f2) fi # single core = 743MiB/s < /dev/zero openssl enc -aes-128-ctr -K $key -iv $iv 2>/dev/null # single core = 184MiB/s # openssl rand 2000000000 } export -f randdata ints() { # Convert random data on stdin to numbers $from..$to in $fmt from=$1 to=$2 fmt="$3" # Allow up to 2^64 perl -e '$diff='$to-$from'+1; $factor = 2**64/$diff; while(sysread(STDIN,$buf,65536)) { print map { sprintf("'"$fmt"'", int($_ / $factor) + '$from'); } unpack("Q*",$buf); }' } export -f ints randints() { randdata | ints "$@" } export -f randints # Default format of ints fmt='%s\n' while true; do case "$1" in -f | --fmt ) fmt="$2"; shift 2 ;; -s | --seed ) seed="$2"; shift 2 ;; -D | --debug ) debug=true; shift ;; -h | --help ) help=1; shift 2 ;; -- ) shift; break ;; * ) break ;; esac done qfmt="$(parallel --shellquote --shellquote ::: "$fmt")" if [ "$seed" == "" ] ; then if [ "$1" == "" ] ; then # Boost performance by running 1 per CPU core eval parallel -u randdata ::: {1..$(parallel --number-of-threads)} else # $1 set => numerical if [ "$2" == "" ] ; then # 0 .. $1 eval parallel -N0 --lb randints 0 $1 "$qfmt" ::: {1..$(parallel --number-of-threads)} else # $1 .. $2 eval parallel -N0 --lb randints $1 $2 "$qfmt" ::: {1..$(parallel --number-of-threads)} fi fi else if [ "$1" == "" ] ; then # Run a single instance randdata else # $1 set => numerical if [ "$2" == "" ] ; then # 0 .. $1 randints 0 $1 "$fmt" else # $1 .. $2 randints $1 $2 "$fmt" fi fi fi