shuffled playlist with mplayer & zsh


Given a folder or folder structure containing media files, mplayer, and zsh, we can easily create a shuffled playlist and play it with:

$ mplayer "${(f)$(find -iname \*.mp3 | shuf)}"

This will correctly pass all of the files to `mplayer` via argv, which should allow normal control via stdin.

Media files are likely to have special characters in their filenames. A more robust version of the above:

$ mplayer "${(0)$(find -iname \*.mp3 -print0 | shuf -z)}"

This will handle the playing of any file with a valid filename (i.e., a filename composed of any non-NUL character.)

The (0) and (f) are “parameter expansion” flags in zsh.

According to the manpage:

f      Split the result of the expansion at newlines. This is a shorthand for `ps:\n:'.
0      Split the result of the expansion on  null  bytes.   This  is  a  shorthand  for `ps:\0:'.

Why these work is a bit tricky, and it’s related to how `zsh` and `mplayer` handle argv and stdin.

Next-time, I’ll verify these by running `zsh` under a debugger and looking at the relevant source (—it’s in subst.c:paramsubst.) We’ll also look at `mplayer` and why the more naïve approach does not work.