how to make ls show hidden files then directories then regular files in order

Posted on

Problem :

Is there a way to get ls to show all dot files including hidden directories first then regular directories then regular files? I have read throughout the ls man page but come up with nothing. I have also searched Super user and although there are some answers to different questions like showing hidden files first or directories first, I haven’t found anything quite in this order.
Thanks

Solution :

The simplest answer is to split it into two commands: this is best done in a script (such as lssort), but if you want ls always to work this way you can alias ls=lssort:-

ls -d --group-directories-first "$@"/.*
ls -d --group-directories-first "$@"/*

This assumes that a single directory name (which may contain spaces) is given and that it is the last parameter passed. Unfortunately this has two limitations:-

  1. The directory must be given: to overcome this you need to scan the parameters to find the last and make different calls if the last parameter is an option or doesn’t exist (replace / by space in the above calls).
  2. If the ls options cause a total line (eg -l) to be output you will get two totals, one for each call.

The first of these is answered by scripting:-

[ $# == 0 ] && lp='' || eval lp="${$#}"
[ "${lp#-}" == "$lp" ] && sl=/ || sl=' '
ls -d --group-directories-first "$@"$sl.*
ls -d --group-directories-first "$@"$sl*

The second requires all the files to be listed in a single command and the output redirected to a temporary file with a succession of grep searches, first for ^total [0-9]*$, then for files beginning with ., then the same search with -v to list the remainder. Thus is easy if ls produces bare file names, but much more complex in the general case, beyond the scope of this answer.

Notes:-

  • ls -d is needed to avoid the expansion of subdirectories.
  • ... && ... || ... is a more compact form of if ...; then ...; else ...; fi.
  • eval was necessary to make bash parse the command line twice: ${$#} gives an error.

I’m going to answer my own question. After more research I have found a way to get what I want.

Although not the exact order in which I initially wanted in the question, I have found a way to do this with the order: All dirs including hidden, then all dot files then all regualr files. With this in .bashrc: alias d=’LC_COLLATE=C ls -la –group-directories-first’. And I’m happy with that.

Leave a Reply

Your email address will not be published. Required fields are marked *