164

I am trying to create an aliases in bash. What I want to do is map ls -la to ls -la | more

In my .bashrc file this is what I attempted:

alias 'ls -la'='ls -la | more'

However it does not work because (I assume) it has spaces in the alias name. Is there a work around for this?

sixtyfootersdude
  • 8,049
  • 16
  • 52
  • 71

4 Answers4

190

The Bash documentation states "For almost every purpose, shell functions are preferred over aliases." Here is a shell function that replaces ls and causes output to be piped to more if the argument consists of (only) -la.

ls() {
    if [[ $@ == "-la" ]]; then
        command ls -la | more
    else
        command ls "$@"
    fi
}

As a one-liner:

ls() { if [[ $@ == "-la" ]]; then command ls -la | more; else command ls "$@"; fi; }

Automatically pipe output:

ls -la
Dennis Williamson
  • 106,229
  • 19
  • 167
  • 187
  • 2
    why do you need to use double brackets inside the if statement? – sixtyfootersdude Feb 08 '10 at 14:55
  • 4
    @sixtyfootersdude: The double-bracket form is more powerful and I use it by habit. See http://mywiki.wooledge.org/BashFAQ/031 – Dennis Williamson Feb 08 '10 at 18:35
  • So what is the final command? alias ls='ls()' ?? – Jeef Apr 01 '15 at 12:39
  • 1
    @Jeef: No, my answer uses a function *instead* of an alias. I have edited it to try to make it clearer. – Dennis Williamson Apr 01 '15 at 14:14
  • What is `command` for here? Why not just `ls -la | more` or `ls "$@"`? – Merlin -they-them- Mar 13 '16 at 16:54
  • 12
    @merlinpatt: `command` prevents the function from being called recursively. – Dennis Williamson Mar 13 '16 at 18:05
  • Very useful, I wanted to use a an alias to replace git push with a behaviour that would change when git push was called from different directories. If you put a function in .bash_aliases it will be usable from your user folder and subfolder, just as an alias would. – Simonlbc May 28 '16 at 12:35
  • @Simonlbc: Note that `.bash_aliases` is most likely a distribution or locally defined feature rather than a default Bash feature. – Dennis Williamson May 28 '16 at 15:14
  • @Simonlbc Instead of modifying the current `git push` behavior, I would suggest creating a new [Git Alias](https://git-scm.com/book/tr/v2/Git-Basics-Git-Aliases), e.g. `git my-push`. – Franklin Yu Aug 08 '16 at 21:55
  • @FranklinYu why? – Simonlbc Aug 09 '16 at 07:23
  • @Simonlbc To make sure that tutorials online will surely work on my environment. Maybe more of a personal choice. – Franklin Yu Aug 09 '16 at 19:19
  • Take care when naming the function that you don't conflict with the `bash-completion` (command autocomplete) function. I spent a bit of time troubleshooting `tmux`, having created a function `_tmux` to which to alias the command, but discovered that the `bash-completion` for `tmux` also used `_tmux` to drive the autocomplete. So, I created the function `_TMUX` instead. – palswim Sep 17 '18 at 20:15
71

From the alias man page:

The first word of each simple command, if unquoted, is checked to see if it has an alias. If so, that word is replaced by the text of the alias. The alias name and the replacement text may contain any valid shell input, including shell metacharacters, with the exception that the alias name may not contain `='.

So, only the first word is checked for alias matches which makes multi-word aliases impossible. You may be able to write a shell script which checks the arguments and calls your command if they match and otherwise just calls the normal ls (See @Dennis Williamson's answer)

heavyd
  • 62,847
  • 18
  • 155
  • 177
  • 11
    +1 For explaining why I am not allowed to use ls -la as an alias. – sixtyfootersdude Feb 08 '10 at 14:49
  • 10
    This was helpful because instead of trying to solve it it answered the question. I came here because i wanted to create an alias with a space in it and that just won't happen. – angryundead Feb 11 '14 at 21:15
  • 1
    This not only answered my question, but gave me valuable insight into how the aliasing mechanism actually works. Your quote from the man page was quite helpful. – Lily Finley Jan 21 '19 at 14:32
22

A slightly improved approach taken from Dennis' answer:

function ls() {
  case $* in
    -la* ) shift 1; command ls -la "$@" | more ;;
    * ) command ls "$@" ;;
  esac
}

Or the one-liner:

function ls() { case $* in -la* ) shift 1; command ls -la "$@" | more ;; * ) command ls "$@" ;; esac }

This allows for further options/arguments to be appended after the command if needed, for example ls -la -h

ld_pvl
  • 339
  • 2
  • 7
  • 2
    How does this handle if I want `ls -lat` to be excluded from this treatment? I would need to put a case to handle it above the `-la*` entry, yes? – Steven Lu Apr 28 '14 at 05:36
  • Thanks. Useful for me with docker : `function d() { case $* in c* ) shift 1; command docker container "$@" ;; n* ) shift 1; command docker network "$@" ;; * ) command docker "$@" ;; esac }` . But unfortunately autocomplete won't work – trogne Oct 11 '20 at 19:36
-1

You can invoke this alias still, but you need quotation in order that the space is part of the command word. So "ls -la" -p pattern will pass the -p pattern option to more, not ls.

Charles Stewart
  • 2,872
  • 1
  • 26
  • 38