我在更深的目录中有很多日志文件,如下所示:
/my/deep/path/to/log/files/
foo-2016-10-10.log
foo-2016-10-11.log
bar-2016-10-10.log
bar-2016-10-11.log
我一天多次发现自己拖着不同的日志:
tail -fn 100 /my/deep/path/to/log/files/foo-2016-10-10.log
除了最终文件之外,是否可以别名? 允许标签完成让我完成其余的工作?
例如,我想输入tl
(尾部日志的简称)和我正在寻找的特定日志文件:
$ tl foo
[HIT TAB KEY]
$ tl foo-2016-10-1
[HIT 1 and TAB KEY]
$ tl foo-2016-10-11.log
bash有可能吗?我怎么能做到这一点?
答案 0 :(得分:3)
几乎是Charles Duffy答案的克隆(唯一的区别是他使用了globs并且我使用compgen
- 这可能是完成(非常)设计的方式写的):
_tl_COMPDIR=/my/deep/path/to/log/files/
_comp_tl() {
local IFS=$'\n'
COMPREPLY=( $(compgen -f -- "$_tl_COMPDIR$2") )
COMPREPLY=( "${COMPREPLY[@]#"$_tl_COMPDIR"}" )
}
tl() (
cd -- "$_tl_COMPDIR" && tail -fn 100 "$@"
)
complete -o nospace -o filenames -F _comp_tl tl
答案 1 :(得分:2)
这有点难看,但是这样做了:
_tl_log_path=/my/deep/path/to/log/files
_tl_completions() {
COMPREPLY=( "${_tl_log_path}/$2"* )
COMPREPLY=( "${COMPREPLY[@]#${_tl_log_path}/}" )
if [[ ${COMPREPLY[0]} = "$2*" ]]; then
COMPREPLY=( )
fi
}
complete -F _tl_completions -o filenames tl
至于你的tl
,我建议你这样做:
tl() {
# generate an array of arguments to pass to tail
local -a args=( )
# iterate over each argument given to the function
for arg; do
if [[ -e "$_tl_log_path/$arg" ]]; then
# if a like-name file exists under _tl_log_path, add that filename as an argument
args+=( "$_tl_log_path/$arg" )
else
# otherwise, add that argument exactly as it already exists
args+=( "$arg" )
fi
done
# ...and, finally, execute the tail command.
tail -f "${args[@]}"
}
...虽然你也可以便宜又轻松:
tl() (
cd "$_tl_log_path" || exit
exec tail -f "$@"
)
解释:
complete -F funcname cmdname
表示应调用shell函数funcname
以确定如何完成命令cmdname
。 -o filenames
进一步表明结果应被视为文件名。COMPREPLY
是一个shell数组,预计完成函数将填写可能的完成。COMPREPLY=( "${_tl_log_path}/$2"* )
将给定内容扩展为glob(因为*
有意地在引号之外)。COMPREPLY=( "${COMPREPLY[@]#${_tl_log_path}/" )
然后将日志目录作为数组中每个结果的前缀。[[ ${COMPREPLY[0]} = "$2*" ]]
(在这种情况下,星号里面引号)是否检测到不存在可能的全局扩展结果的情况,以及(因此)glob扩展到的位置本身(假设shell的shopt
配置是默认值)。答案 2 :(得分:0)
是的,你可以在执行命令之前直接切换到该目录。
$ cd /my/deep/path/to/log/files/
$ tl <tab>