Shuffling mp3 files often results in hearing a track that recently played. So I decided to use the 'touch' command to update the 'last modified' date & time of a file. I want my script to randomly select a song from the 10 songs that I haven't heard in the longest amount of time.
I came up with this:
ls -t $music_folder | tail -n 10 | sort -R | tail -n 1 | while read file; do
echo $music_folder$file
mplayer $music_folder$file
done
I have not yet added the 'touch' line to update the song that's about to play.
This lists the files in $music_folder sorted by time last modified, looks only at the 10 that haven't been touched in the longest time, randomizes the sort order of those ten, then grabs the one at the bottom of the list.
The 'echo' line works perfectly. However, when I try to play the song with mplayer, it tries to play several files where each word of the results is a different file name. Why is it not passing $file as a single string of text? And how can I get mplayer to play the file shown in the echo line?
Put double quotes around the shell variables. For example:
mplayer "$music_folder$file"
The problem is that bash, like all other POSIX shells, performs pathname expansion and word splitting on unquoted shell variables. To illustrate, let's work in a directory with three files:
$ ls
1.mp3 2.mp3 3.mp3
Now, let's define a variable and expand it without quoting:
$ var="dir/Joe's song *.mp3"
$ printf "%s\n" $var
dir/Joe's
song
1.mp3
2.mp3
3.mp3
Observe that dir/Joe's
and song
were separated: this is word splitting. Further, *.mp3
became a list of files in the directory: this is pathname expansion. Both of these, however, can be suppressed with the use of double quotes:
$ printf "%s\n" "$var"
dir/Joe's song *.mp3
This is what you wanted.
For completeness, let's consider single-quotes:
$ printf "%s\n" '$var'
$var
Inside single-quotes, the shell expands nothing. Consequently, as shown above, the even four characters $var
remain unchanged.