Is there any command to list the contents if passed a directory, but output the contents if it's a file?

For example, often when I am navigating the directory structure I will start typing into the terminal something like

ll /etc/path/  # I see a file in tab-completion that interests me, called myfile.txt
ll /etc/path/myfile.txt  # I do the auto-completion to get it into the command line
less /etc/path/myfile.txt  # Now I have to go back and change 'll' to 'less'

Alternatively, if I'm looking for a file, I start with

less /etc/path  # I see in tab-completion several files that might interest me, so I need to know more
ll /etc/path  # See more info about file sizes, etc, so I can choose the file I want. Have to change 'less' to 'll'
less /etc/path/myfile.txt  # Now that I know which file I want, I have to go back and change 'll' to 'less'

This is something I end up doing dozens of times a day, and starts to slow me down. Is there a command or script that does the likeliest scenario for you? For example

some-program /etc/path/to/file/or/directory

If the target is a text file or symlink to a text file, 'less /etc/path/to/.....' would be executed. But if it were anything else, e.g. directory, binary file, block device, it would do 'll /etc/path/to/......'

Of course if it does something you don't want, like 'less' on a file symlink but you want to see the symlink itself with 'll', then you just run 'll' manually.

Anything like this exist (I bet it's out there, it seems like such a common task)? Or am I just using Linux command line in an inefficient way and there are better ways to navigate through it...how do you do it? Or I am really the only one going back and forth in the command line all the time switching 'less' to 'll' and back again?

some-program() {
  if [[ $# > 1 ]]; then
    echo "Only one argument supported at this time"
  exit 1
  if [[ $# == 0 ]]; then
  if [[ -d $ELEMENT ]]; then
    ls --color=auto -alF "$ELEMENT"
    less "$ELEMENT"
  • Your script seems OK. It will use less to show the file content if applied to a file, and it will list the directory if applied to a directory. I have one point only which is you defined a function and you did not invoke it. You just need to remove the first line and last one.
    – Khaled
    Commented Mar 17, 2013 at 12:20
  • Or put this inside your .profile or .bashrc Commented Mar 17, 2013 at 15:41
  • Have you considered actually using your command history? Try the arrow keys on your keyboard... Commented Mar 18, 2013 at 11:36

1 Answer 1


less has a really neat built-in feature that lets you do things like this. See the lesspipe man page.

To use that feature to automatically show a directory listing of directories, do the following:

  1. Set up lesspipe following the man page: eval "$(lesspipe)"

  2. Create ~/.lessfilter with the following contents and make it executable:

    if [ -d "$1" ]; then
        ls -alF "$1"
        # We don't handle this format.
        exit 1
    exit 0

This sets up a filter script run by lesspipe to handle file types. It checks to see if what you're trying to view is a directory and, if so, runs ls instead.

Your original request included color. That's unfortunately a bit harder, since less doesn't show color by default and the output from the filter script is still piped through less. You'd need to use -R as a default option (which is probably not a good idea if you ever view a binary file) to do that. I don't think there's a way to have the lessfilter script tell less to add a new option.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .