alphekka alphekka - 1 month ago 6
Linux Question

Bash Array Script Exclude Duplicates

So I have written a bash script (named music.sh) for a Raspberry Pi to perform the following functions:


  • When executed, look into one single directory (Music folder) and select a random folder to look into. (Note: none of these folders here have subdirectories)

  • Once a folder within "Music" has been selected, then play all mp3 files IN ORDER until the last mp3 file has been reached

  • At this point, the script would go back to the folders in the "Music" directory and select another random folder

  • Then it would again play all mp3 files in that folder in order

  • Loop indefinitely until input from user



I have this code which does all of the above EXCEPT for the following items:


  • I would like to NOT play any other "album" that has been played before

  • Once all albums played once, then shutdown the system



Here is my code so far that is working (WITH duplicates allowed):

#!/bin/bash
folderarray=($(ls -d /home/alphekka/Music/*/))
for i in "${folderarray[@]}";
do
folderitems=(${folderarray[RANDOM % ${#folderarray[@]}]})
for j in "${folderitems[@]}";
do
echo `ls $j`
cvlc --play-and-exit "${j[@]}"
done
done
exit 0


Please note that there isn't a single folder or file that has a space in the name. If there is a space, then I face some issues with this code working.

Anyways, I'm getting close, but I'm not quite there with the entire functionality I'm looking for. Any help would be greatly appreciated! Thank you kindly! :)

Answer

Use an associative array as a set. Note that this will work for all valid folder and file names.

#!/bin/bash

declare -A folderarray
# Each folder name is a key mapped to an empty string
for d in /home/alphekka/Music/*/; do
  folderarray["$d"]=
done

while [[ "${!folderarray[*]}" ]]; do
  # Get a list of the remaining folder names
  foldernames=( "${!folderarray[@]}" )
  # Pick a folder at random
  folder=${foldernames[RANDOM%${#foldernames[@]}]}
  # Remove the folder from the set
  unset "foldernames[$folder]"
  for j in "$folder"/*; do
    cvlc --play-and-exit "$j"
  done
done