Search code examples
linuxzsh

zsh or bash set default variable in alias declaration


this is the desired command for context:

alias ls-last='ls -ltr | tail -n ${$1:20}' 

but this doesn't work with

zsh: bad substitution
[1]    broken pipe  ls -ltr                                                                                                                                                                                                                                         

What I'm trying to do is be able to run ls-last 10 for the last 10, but if just ls-last then it would default to 20. What is the best way to do that in this context (a single line) that would work for bash and zsh?


Solution

  • There are three problems here:

    1. ${$1:...} is an invalid parameter expansion in bash
    2. Aliases don't take arguments; $1 is one of to current shell's positional parameter, not the "argument" to the alias.
    3. The default-value operator is either - or :-, not : alone.

    Fixing all three at once using a function:

    ls-last () {
        ls -ltr | tail -n "${1:-20}"
    }
    

    However, this is fragile, as file names can contain newlines, making the assumption that the output of ls contains exactly one file name per line untrue.


    As you mention zsh, you can do this with a regular glob, not the ls command:

    ls-last () {
        print -l *(Om[-${1:-20},-1])
    }
    

    The glob qualifiers in (...) modify the result of the glob *:

    1. Om sorts the results by modification date, like ls -tr.
    2. [-x, -1] returns just the last x results.