Goga Benton
Goga Benton

Reputation: 61

bash. How to pick random line from a variable containing numerous lines?

a=$(find ./ -name "*-*.txt")

Now I need to get random line from $a, but shuf yelling at me

b=$(shuf -n1 $a)

shuf: extra operand

What's my issue? Thank you!

Upvotes: 1

Views: 725

Answers (2)

user6576367
user6576367

Reputation:

You can use $RANDOM for this.

Notes:

  • ${#array[@]} gives the size of the array
  • $((min + RANDOM % max)) gives you a random integer, whereas max is not included.
  • You can access an array item at index index_number like so ${array[index_number]}
# define array
a=()
while read line
do
    # read the file list line by line and add to the array
    a+=("$line")
done < <(find ./files -name '*-*.txt')

random_index=$((0 + RANDOM % ${#a[@]}))

echo ${a[$random_index]}

Upvotes: 1

Gordon Davisson
Gordon Davisson

Reputation: 125828

By default, shuf takes a single filename argument, and shuffles the contents of that file. You want it to shuffle its arguments instead; for that, use shuf -e:

b=$(shuf -e -n1 $a)

BTW, there's a subtler problem with this: it'll get confused by filenames with spaces and/or wildcard characters. Maybe not going to happen in your environment, but I prefer to use scripting idioms that don't fall over due to funny filenames. To protect against that, store the filenames in an array rather than counting on word splitting to tell where one stops and the next begins:

readarray -d '' -t arr < <(find ./ -name "*-*.txt" -print0)
b=$(shuf -en1 "${arr[@]}")

If you don't need to store the file list, things are even simpler:

b=$(find ./ -name "*-*.txt" -print0 | shuf -zn1 | tr -d '\0')

Upvotes: 1

Related Questions