This is an even later answer to the late @gniourf_gniourf answer that I just supported, because it is by far the best answer, twice. (Once to avoid eval and once to safely process file names.)
But it took me a few minutes to unravel the "not very well-documented" functions (s) that this answer uses. If your Bash skills are strong enough that you immediately saw how it works, skip this comment. But I did not, and, unraveling it, I think it is worth explaining.
Function # 1 is the copied file. a=(*) creates an array of $a whose members are the files in the current directory. Bash understands all the oddities of file names, so the list is guaranteed to be correct, guaranteed to be escaped, etc. No need to worry about parsing textual file names returned by ls correctly.
Feature # 2 - Bash parameter extensions for arrays , one nested in the other. This starts with ${#ARRAY[@]} , which expands to the length of $ARRAY .
This extension is then used to index the array. The standard way to find a random number between 1 and N is to take a random number modulo N. We need a random number between 0 and the length of our array. Here's a two-line approach for clarity:
LENGTH=${#ARRAY[@]} RANDOM=${a[RANDOM%$LENGTH]}
But this solution does it on one line, removing unnecessary variable assignment.
Function # 3 is a Bash bracket extension , although I must admit that I do not quite understand This. For example, to expand the list, 25 files are used with the name filename1.txt , filename2.txt , etc.: echo "filename"{1..25}".txt" .
The expression inside the subshell above, "${a[RANDOM%${#a[@]}]"{1..42}"}" , uses this trick to create 42 separate extensions. An extension of the bracket places one digit between ] and } , which, at first, I thought, signed the array, but if so, it will be preceded by a colon. (He would also return 42 consecutive elements from a random spot in the array, which is not at all the same as returning 42 random elements from an array.) I think this just makes the shell run the extension 42 times, thereby returning 42 random elements from array. (But if someone can explain it more fully, I would like to hear it.)
The reason N must be hard-coded (up to 42) is because the extensions expand before the variable expands.
Finally, here is Function # 4 , if you want to do this recursively for a directory hierarchy:
shopt -s globstar a=( ** )
This includes the shell option , which causes ** to match recursively. Now your $a array contains all the files in the entire hierarchy.