Very often I find myself looking through directories using 'ls', then when I find the file I want, I use 'less' to look at the file.

So for example to find a mysql log file I might type
ls /var

ls /var/log/

and then:
ls /var/log/mysql

and finally:
less /var/log/mysql/mysql.log

(its a bit of a contrived example, but hopefully you know what I am doing)

I find it annoying that I need to decide if the command should be ls or less. Why can't 'less' determine if it has been given a directory and act as 'ls' ?

Is there a command that I can use instead of less that will act as ls or less depending on the file type ? Or is there a common alias that people use ?

  • 2
    You're doing it wrong... – ewwhite Jan 2 '14 at 15:26
  • 3
    @ewwhite Maybe you could be helpful and explain to him why it's wrong? – ceejayoz Jan 2 '14 at 15:41
  • @ceejayoz I'm not sure I can. These are discrete commands. It's like trying to describe the color "blue". – ewwhite Jan 2 '14 at 15:43
  • 3
    @ewwhite I'll take a stab at it - "less works on files, not directory listings, and while you'd like it to work as ls on a directory, others would have different desires in that situation - it's better to just fail predictably. In most cases, you'll know in advance if something is a folder or a directory and get used to just using the right command in the first place." – ceejayoz Jan 2 '14 at 15:49
  • 2
    What version of less are you using? Recent versions (mine is 444) do exactly what you want automatically. – depquid Jan 2 '14 at 17:16

Less can determine if it has been given a directory. Set the LESSOPEN environment variable to ~/bin/LESSPIPE and make ~/bin/LESSPIPE a script like the following:

if [ -d "$1" ]; then
  exec /bin/ls -la "$1"
elif [ -f "$1" ]; then
  case "$1" in
    *.tar|ztar) exec tar tvvf "$1" 2>/dev/null;;
    *.tar.[dg]z|*.tar.z|*.tgz) exec gzip -dc "$1" | tar tvvf - 2>/dev/null;;
    *.tar.bz2) exec bzip2 -d <"$1" 2>/dev/null | exec tar tvvf - 2>/dev/null;;
    *.tar.Z|*.taz) exec uncompress -c "$1" | exec tar tvvf - 2>/dev/null;;
    *.zip) exec unzip -l "$1" 2>/dev/null;;
    *.lha) exec lha -v "$1" 2>/dev/null;;
    *.7z) exec 7z l "$1" 2>/dev/null;;
    *.[rs]pm) exec rpm -qilp "$1";;
    *.z|*.[dg]z) exec gzip -dc "$1" 2>/dev/null;;
    *.bz2) exec bzip2 -dc "$1";;
    *.xz) exec xz -dc "$1";;
    *.Z) exec uncompress -c "$1" 2>/dev/null;;

You'll get a listing for directories and archives.

You can use lesskey instead of the environment variable to set the preprocessor. See the documentation for details.

  • 1
    I got this to work on ubuntu 12.04 by doing export LESSOPEN="|~/bin/LESSPIPE %s". It does exactly what I want and a whole lot more useful stuff. – Philip Clarke Jan 4 '14 at 0:15

In bash you could easily create a function to do this:

function less_ls()
  # True if file exists and is a regular file.
  if [ -f "${1}" ]
    less "${1}"
    ls "${1}"

Obviously you can rename the function into whatever you want by replacing the less_ls part, if you name it less it will have precedence of the executable less. If you want this to be defined automatically every time you start Bash you could copy paste it into your ~/.bashrc file.

  • 3
    Or the OP could use the right commands... +1 for the workaround. – ewwhite Jan 2 '14 at 15:32
  • 7
    Sure, he could, but he says he doesn't want to. It's not up to me to tell people what they have to prefer. – replay Jan 2 '14 at 15:32

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.