Linux – How to list files in a specific order according to directory in bash

bashcommand linelinuxshellunix

I have a bunch of directories each containing a bunch of files. Normally I can list all of the files with ls */*.*
but this always lists them according to alphabetical order on the directories, then alphabetical order within each directory. So it will always output

dir1/file1.foo
dir1/file2.foo

dir2/file1.foo
dir2/file2.foo


dirN/file1.foo
dirN/file2.foo

What I'd like it to do instead is output it so that the directories are arranged in some specific order (for example, in reverse), but have all the files within each directory in normal order, like so:

dirN/file1.foo
dirN/file2.foo


dir1/file1.foo
dir1/file2.foo

Using ls -r */*.* doesn't do what I want because it reverses the order within each directory as well as the order of the directories themselves. I have tried using ls `ls -r` which does what I want for the directory names that have no spaces in them, but won't work for the ones that do (which is unfortunately most of them). If I try instead ls "`ls -r`" then it outputs the same thing as ls -r – a list of directory names, but in reverse. How do I get bash to do what I want?

Best Answer

Using the sort command:

ls */* | sort -rst '/' -k1,1

with:

  • -t '/' to change the field separator
  • -r to do a reverse sort
  • -s to ensure the sort is stable (in other words, it doesn't change order beyond the specified columns
  • -k1,1 to restrict the sort to the first column

This assumes that the output of ls */* is already sorted (which it should be), otherwise add a plain sort stage in the middle.