sargas
sargas

Reputation: 558

Bash: Pass alias or function as argument to program

Quite often i need to work on the newest file in a directory.

Normally i do:

ls -rt

and then open the last file in vim or less.

Now i wanted to produce an alias or function, like

lastline() {ls -rt | tail -n1}
# or
alias lastline=$(ls -rt | tail -n1)

Calling lastline outputs the newest file in the directory, which is nice. But calling

less lastline

wants to open the file "lastline" which doesn't exist.

How do i make bash execute the function or alias, if possible without a lot of typing $() or ``? Or is there any other way to achieve the same result?

Thanks for your help.

Upvotes: 1

Views: 111

Answers (2)

gniourf_gniourf
gniourf_gniourf

Reputation: 46823

You're parsing ls, and this is very bad. Moreover, if the last modified “file” is a directory, you'll be lessing/viming a directory.

So you need a robust way to determine the last modified file in the current directory. You may use a helper function like the following (that you'll put in your .bashrc):

last_modified_regfile() {
    # Finds the last modified regular file in current directory
    # Found file is in variable last_modified_regfile_ret
    # Returns a failure return code if no reg files are found
    local file
    last_modified_regfile_ret=
    for file in *; do
        [[ -f $file ]] || continue
        if [[ -z $last_modified_regfile_ret ]] || [[ $file -nt $last_modified_regfile_ret ]]; then
            last_modified_regfile_ret=$file
        fi
    done
    [[ $last_modified_regfile_ret ]]
}

Then you may define another function that will vim the last found file:

vimlastline() {
    last_modified_regfile && vim -- "$last_modified_regfile_ret"
}

You may even have last_modified_regfile take optional arguments: the directories where it will find the last modified regular file:

last_modified_regfile() {
    # Finds the last modified regular file in current directory
    # or in directories given as arguments
    # Found file is in variable last_modified_regfile_ret
    # Returns a failure return code if no reg files are found
    local file dir
    local save_shopt_nullglob=$(shopt -p nullglob)
    shopt -s nullglob
    (( $# )) || set .
    last_modified_regfile_ret=
    for dir; do
        dir=${dir%/}
        [[ -d $dir/ ]] || continue
        for file in "$dir"/*; do
            [[ -f $file ]] || continue
            if [[ -z $last_modified_regfile_ret ]] || [[ $file -nt $last_modified_regfile_ret ]]; then
                last_modified_regfile_ret=$file
            fi
        done
    done
    $save_shopt_nullglob
    [[ $last_modified_regfile_ret ]]
}

Then you can even alter vimlastline accordingly:

vimlastline() {
    last_modified_regfile "$@" && vim -- "$last_modified_regfile_ret"
}

Upvotes: 2

anubhava
anubhava

Reputation: 785088

Use command substitution like this:

lastline() { ls -rt | tail -n1; }
less "$(lastline)"

Or pipe it to xargs:

lastline | xargs -I {} less '{}'

Upvotes: 0

Related Questions