Here is a shell fragment that relies only on POSIX functions and handles arbitrary file names (but skips point files from selection). Random selection uses awk because everything you get in POSIX. This is a very bad random number generator because awk RNG is seeded by the current time in seconds (therefore, it is easily predictable and returns the same choice if you call it several times per second).
set -- * n=$(echo $# | awk '{srand(); print int(rand()*$0) + 1}') eval "file=\$$n" echo "Processing $file"
If you do not want to ignore point files, the file name generation code ( set -- * ) should be replaced with something more complex.
set -- *; [ -e "$1" ] || shift set .[!.]* "$@"; [ -e "$1" ] || shift set ..?* "$@"; [ -e "$1" ] || shift if [ $# -eq 0]; then echo 1>&2 "empty directory"; exit 1; fi
If you have OpenSSL, you can use it to generate random bytes. If you do not, but your system has /dev/urandom , replace the call to openssl with dd if=/dev/urandom bs=3 count=1 2>/dev/null . Here is a snippet that sets n to a random value between 1 and $# , trying not to enter an offset. This snippet assumes $# at most 2 ^ 23-1.
while n=$(($(openssl rand 3 | od -An -t u4) + 1)) [ $n -gt $((16777216 / $# * $#)) ] do :; done n=$((n % $#))
Gilles Jul 19 '11 at 12:55 2011-07-19 12:55
source share