Code me a Jam!!

Dyalog APL, 78 75 73

{0::'Sorry Joe, no Jams!'⋄⎕SH⍵,{⍵⊃⍨?≢⍵}⎕SH∊'dir/b '⍵'*.mp3'}'%HOMEPATH%\'

Explanation:

{...} unnamed function, wherein represents whatever is to the right of the }
APL statements (separated by ) are executed leftmost first, but each statement is evaluated from right to left (no precedence rules), so each function gets whatever is to its right as argument
0:: sets a trap for all errors to return the string instead
∊'dir/b '⍵'*.mp3' makes the three strings into a single string
⎕SH passes its argument to cmd.exe
?≢⍵ random 1 ≤ integer ≤ count (or 0 < float < 1 if count is 0)
⍵⊃⍨ pick that element (floats are invalid indices, so an error is triggered here if count was 0)
⍵, prepends the home dir
⎕SH passes its argument to cmd.exe


PowerShell, 59 52 bytes

ii(ls -r./*.mp4|random);(,"Sorry Joe, no Jams!")[$?]

-7 byte golf improvements, thanks to Jaykul:

  • Use ii (Invoke-Item) instead of saps
  • No need to use Get- in Get-noun commandlet names, it will be searched by default.
  • No space needed after -r

Previously at 59 bytes

saps(ls -R ~/*.mp3|Get-Random);(,"Sorry Joe, no Jams!")[$?]

It will throw an error if there are no files, but it will print the message too.

Explanation:

  • saps is an alias for Start-Process
  • ls is an alias for Get-ChildItem
  • ~ maps to the home directory, and -R is -Recurse
  • Get-Random selects a random item from the pipeline.
  • After trying to launch it, it uses the previous command exit value as an index into a two-item array which either does nothing, or returns the apology message.