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-open,sqlite3和其他应用程序。
alias lastest="vim `ls -t | grep -vE "^total [0-9]*$" | head -n1`"
Run Code Online (Sandbox Code Playgroud)
您可以在 中轻松配置它zsh,例如使用以下内容:
zstyle ':completion:*' file-sort date
Run Code Online (Sandbox Code Playgroud)
(您也可以更改行,使此样式仅用于某些文件名模式)
zsh 与 bash 非常相似,您可以将其称为 bash 的超集 - 功能/使用明智。
但也许 bash 也有类似的功能。
只需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像以前一样做。
修改 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 日更新:修复了上次更新后在当前目录上操作时的错误。