Suppose the application can only open files via command line arguments, how would i go about randomizing a list of file names/paths to accomplish this?

I thought this should be fairly easy but apparently spaces make it more complicated than it should be.

An example:

with space.mp3

When i try $(ls | shuf) the space is not escaped yielding something like with space.mp3 b.mp3 a.mp3.

Using the quote option -Q does not help either because the command substitution escapes the quotes resulting in the following: \"with space.mp3\" \"a.mp3\" \"b.mp3\"

Similarly the escapes of -b get escaped as well: with\\ space.mp3 a.mp3 b.mp3

Something like find's -exec <application> {} \+ without the finding would be perfect...


Here is a zsh-only variant, getting rid of ls as well as shuf:

mplayer *.mp3(oe:REPLY=\$RANDOM:)

The Glob Qualifier o executes (e) the code between both colons (:). The code in turn assigns every file a pseudo-random number $RANDOM, resulting in an arbitrary order.

To obscure the command a little more, but mainly to save key strokes, you can define a shell function s:

mplayer *.mp3(oe:s:)

Or, even better, define a key binding, e.g. for CTRL+R for the shuffle part:

bindkey -s '^R' '(oe:REPLY=\\$RANDOM:)^M'

Now, type only mplayer *.mp3 followed by CTRL+R, and the (oe:REPLY=\$RANDOM:) part gets appended and the command line immediately executed (^M).


You don't need ls at all. Try

mplayer "${(f)$(shuf -e *.mp3)}"

The problem with ls is that it is often aliased to something like ls --color=always and in that case prints invisible characters which are not recognized properly by other programs (shuf in this example).

  • I know that i do not need ls, but ls is not the problem in any case, the problem is zsh escaping characters it should not escape. Also i don't get why anyone would be using color=always instead of auto... – H.B. Sep 2 '14 at 2:08
  • Sometimes "always" can be really useful, e.g. when there is a lot of files in directory: cd /usr/bin; ls -l | less. – jimmij Sep 2 '14 at 3:07
  • I presume you mean less -R, otherwise the colour chars are encoded. Supposed one could use it for that, i usually execute ls and scroll the terminal itself. – H.B. Sep 2 '14 at 4:22
  • @H.B.: Sorry to say that, but you shouldn't parse the the output of ls... so I would identify indeed the ls as the problem. – mpy Sep 2 '14 at 17:10
  • @mpy: Not buying it, ls -b works just fine. – H.B. Sep 2 '14 at 17:24

I think i finally figured out a method: ${(f)"$(ls | shuf)"}


ls | shuf: Shuffle files/dirs as expected.
"$(...)": The quotes maintain the output as it is, including newlines.
${(f)...}: Splits the result of the expansion at newlines yielding an array of the file/dir names.

"${(f)$(ls | shuf)}" works as well, ${(f)$(ls | shuf)}, does not.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.