自动完成最新文件

dot*_*hen 15 bash autocomplete

我有一个创建文本文件的过程,其文件名基于其创建时刻的时间戳:

$ ls
1378971222.txt
1378971254.txt
1378971482.txt
1378971488.txt
1378972089.txt
1378972140.txt
1378972141.txt
1378972153.txt
1378972155.txt
1378972241.txt
Run Code Online (Sandbox Code Playgroud)

我如何自动完成最新创建的文件的文件名,即具有最新 mtime 的文件?无法对这些文件使用制表符补全,因为文件名中的几乎每个字符都与另一个文件共享。我希望找到一个快捷方式(例如Alt .自动完成最后一个命令的最后一个参数)。我已成功地炮制以下别名这是伟大的VIM,但我很想知道,如果一个通用的快捷方式存在,我可以用用kde-opensqlite3和其他应用程序。

alias lastest="vim `ls -t | grep -vE "^total [0-9]*$" | head -n1`"
Run Code Online (Sandbox Code Playgroud)

max*_*zig 7

您可以在 中轻松配置它zsh,例如使用以下内容:

zstyle ':completion:*' file-sort date
Run Code Online (Sandbox Code Playgroud)

(您也可以更改行,使此样式仅用于某些文件名模式)

zsh 与 bash 非常相似,您可以将其称为 bash 的超集 - 功能/使用明智。

但也许 bash 也有类似的功能。


ter*_*don 6

只需vim从别名中删除。做这样的事情:

alias latest='ls -tr | tail -n 1'
Run Code Online (Sandbox Code Playgroud)

然后您可以使用任何程序打开最新的文件:

emacs `latest`
ls `latest`
mv `latest` ../
Run Code Online (Sandbox Code Playgroud)

等等。

但是,如果您的文件名有空格或奇怪的字符,这将中断,这就是为什么您永远不应该解析ls. 更好的方法是这样的(将其添加到您的.bashrc):

function latest(){
  $1 "$(find . -type f -printf "%C@ %p\n" | sort | tail -n 1 | cut -d " " -f 2-)"
}
Run Code Online (Sandbox Code Playgroud)

此函数将执行您作为参数提供的任何命令,并将find调用结果(最新文件)传递给该命令。因此,您可以执行以下操作:

latest emacs
latest less
Run Code Online (Sandbox Code Playgroud)

如果你需要能够做这样的事情,mv $(latest) foo/试试这个:

function latest(){
   A=(${@})
   prog=$1;
   lat=$(find . -type f -printf "%C@ %p\n" | sort | tail -n 1 | cut -d " " -f 2-)
   if [ ! -z $2 ] ; then 
     args=${A[@]:1}; 
     $prog "$lat" "${A[@]:1}"
   else
     $prog "$lat"
   fi
}
Run Code Online (Sandbox Code Playgroud)

然后,要将最新的文件复制到bar/,您将执行

latest cp bar
Run Code Online (Sandbox Code Playgroud)

你仍然可以latest emacs像以前一样做。


Com*_*lio 3

修改 bash 补全“_filedir”函数以允许使用最后一个文件名进行制表符补全。这是一个可以执行此操作的脚本source

#!/bin/sh

_filedir_newest()
{
    local parent="$1"
    if [ "${#parent}" -gt "0" ]; then
        parent="$(compgen -d -- ${1:0:-1})/"
    fi
    newest=$(bash -c "ls -tr $parent | tail -n 1")
    echo "$parent$newest"
} # _filedir_newest()

_filedir()
{
    local IFS=$'\n'

    _tilde "$cur" || return

    local -a toks
    local x reset
    local newest=0

    reset=$(shopt -po noglob); set -o noglob
    toks=( $(compgen -d -- "$cur") )
    IFS=' '; $reset; IFS=$'\n'

    if [[ "$1" != -d ]]; then
        local quoted
        if [[ "$cur" = "?" ]] || [[ "${cur: -2}" = "/?" ]]; then
            cur="${cur:0:-1}"
            newest=1
        fi
        _quote_readline_by_ref "$cur" quoted

        # Munge xspec to contain uppercase version too
        # http://thread.gmane.org/gmane.comp.shells.bash.bugs/15294/focus=15306
        local xspec=${1:+"!*.@($1|${1^^})"}
        reset=$(shopt -po noglob); set -o noglob
        toks+=( $(compgen -f -X "$xspec" -- $quoted) )
        IFS=' '; $reset; IFS=$'\n'

        # Try without filter if it failed to produce anything and configured to
        [[ -n ${COMP_FILEDIR_FALLBACK:-} && -n "$1" && ${#toks[@]} -lt 1 ]] && {
            reset=$(shopt -po noglob); set -o noglob
            toks+=( $(compgen -f -- $quoted) )
            IFS=' '; $reset; IFS=$'\n'
        }
    fi

    if [[ ${#toks[@]} -ne 0 ]]; then
        # 2>/dev/null for direct invocation, e.g. in the _filedir unit test
        compopt -o filenames 2>/dev/null
        if [[ $newest -eq 1 ]]; then
            COMPREPLY+=( $(_filedir_newest "$cur") )
        else
            COMPREPLY+=( "${toks[@]}" )
        fi
    fi
} # _filedir()

_filedir_xspec()
{
    local cur prev words cword
    _init_completion || return

    _tilde "$cur" || return

    local IFS=$'\n' xspec=${_xspecs[${1##*/}]} tmp
    local -a toks
    local newest=0

    if [[ "$cur" = "?" ]] || [[ "${cur: -2}" = "/?" ]]; then
        cur="${cur:0:-1}"
        newest=1
    fi

    toks=( $(
        compgen -d -- "$(quote_readline "$cur")" | {
        while read -r tmp; do
            printf '%s\n' $tmp
        done
        }
        ))

    # Munge xspec to contain uppercase version too
    # http://thread.gmane.org/gmane.comp.shells.bash.bugs/15294/focus=15306
    eval xspec="${xspec}"
    local matchop=!
    if [[ $xspec == !* ]]; then
        xspec=${xspec#!}
        matchop=@
    fi
    xspec="$matchop($xspec|${xspec^^})"

    toks+=( $(
        eval compgen -f -X "'!$xspec'" -- "\$(quote_readline "\$cur")" | {
        while read -r tmp; do
            [[ -n $tmp ]] && printf '%s\n' $tmp
        done
        }
        ))

    if [[ ${#toks[@]} -ne 0 ]]; then
        compopt -o filenames
        if [[ $newest -eq 1 ]]; then
            COMPREPLY=( $(_filedir_newest "$cur") )
        else
            COMPREPLY=( "${toks[@]}" )
        fi
    fi
} # _filedir_xspec()
Run Code Online (Sandbox Code Playgroud)

可以将其添加到您的~/.bashrc像这样(/path/to/the/script适当替换),以便它适用于所有 bash 会话:

source /path/to/the/script/_filedir.sh
Run Code Online (Sandbox Code Playgroud)

安装后,“?” 用作目录中最后一个文件的特殊指示符,例如:

eog ~/Downloads/?<TAB>
Run Code Online (Sandbox Code Playgroud)

变成(在一种情况下):

eog ~/Downloads/Sunscreen\ Permission\ -\ ToddlerPrimaryElementary.pdf
Run Code Online (Sandbox Code Playgroud)

该技术适用于任何目录,因为它与 bash 完成系统集成,而不仅仅是报告当前目录中的最新文件。我经常使用此功能将最近下载的文件从浏览器移动到我正在积极处理的任何项目的文件夹中 ( mv ~/Downloads/?<TAB> .)。

2021 年 10 月 27 日更新:_filedir_xspec现在也可与bash 自动完成例程一起 使用。 2021 年 11 月 9 日更新:修复了上次更新后在当前目录上操作时的错误。