-1

I want to run mplayer on all files in a folder, sorted by size.

I tried the following commands

ls -1S folder | mplayer
ls -1S folder | xargs mplayer
ls -1S folder | xargs -print0 mplayer

but none of these are working.

How to do it right?

Alex
  • 41,580
  • 88
  • 260
  • 469

2 Answers2

1

Don’t parse the output of ls.

Instead, use e.g. for to loop over the files and call stat to get the file sizes. To avoid issues with spaces or newlines in filenames, use zero-terminated strings to sort etc.:

for file in folder/*; do
    printf "%s %s\0" "$(stat -c %s "$file")" "$file"
done \
| sort -z -k1 -t ' ' \
| cut -z -f2- -d ' ' \
| xargs -0 mplayer

To call mplayer individually for each file (rather than only once, passing all files as arguments), you’ll need to use a while loop, and pipe in the above. Unfortunate | doesn’t work with while (at least I don’t know how), you need to use process substitution instead:

while IFS= read -r -d '' file; do
    mplayer "$file"
done < <(
    for file in folder/*; do
        printf "%s %s\0" "$(stat -c %s "$file")" "$file"
    done \
    | sort -z -k1 -t ' ' \
    | cut -z -f2- -d ' '
)

Note that the above is Bash code, and uses GNU extensions, it works on Linux but it won’t work without changes e.g. on macOS (BSD cut has no -z flag, and stat -c %s needs to be changed to stat -f %z).

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 1
    op wants the files sorted by filesize though – MarcoLucidi Sep 03 '21 at 12:47
  • @MarcoLucidi Thanks, I hadn’t paid attention. I think my edit should address OP’s issue now. – Konrad Rudolph Sep 03 '21 at 13:03
  • play.sh: line 3: syntax error near unexpected token `<' play.sh: line 3: `done < <(' – Alex Sep 03 '21 at 13:07
  • @Alex Sorry, I should have said, this is Bash code. It looks like you are running on POSIX shell (dash or similar)? – Konrad Rudolph Sep 03 '21 at 13:09
  • Never mind, I will use python. I thought there was a simple solution, but I was wrong. With python, I understand what is going on as well – Alex Sep 03 '21 at 13:10
  • 1
    Yes, you’d think that working with lists of files would be the one thing that the shell knows how to do well but nope. It’s really quite frustrating. (The code *can* be made to work on POSIX Bourne Shell using fifos or temporary files instead of the process substitution, but that doesn’t really reduce the complexity). – Konrad Rudolph Sep 03 '21 at 13:12
0

I created a python script to build an executable file for just that I want to do. Here is the complete python code:

import os
import re
import sys
import glob

dir_name = sys.argv[1]

# Get a list of files (file paths) in the given directory 
list_of_files = filter( os.path.isfile,
                        glob.glob(dir_name + '/*') )

# Sort list of files in directory by size 
list_of_files = sorted( list_of_files,
                        key =  lambda x: os.stat(x).st_size)

# Iterate over sorted list of files in directory and 
# print them one by one along with size
for elem in list_of_files[::-1]:
    file_size  = os.stat(elem).st_size 
    print(f"mplayer {re.escape(elem)}")

You redirect the output to a file and execute this. And voila - mplayer plays the files in the order from big to small.

Alex
  • 41,580
  • 88
  • 260
  • 469