在vim中打开最近修改的文件

在vim中打开最近修改的文件

以下命令有效

$ ls -1t | head -1
git_sync_log20180924_00.txt

$ vi git_sync_log20180924_00.txt

但这并不

$ ls -1t | head -1 | vi
Vim: Warning: Input is not from a terminal
Vim: Error reading input, exiting...
Vim: preserving files...
Vim: Finished.

我怎样才能做到这一点(在 vi 中打开最近修改的文件)?

答案1

vi -- "$(ls -t | head -n 1)"

(假设文件名不包含换行符)。

或者如果使用zsh

vi ./*(om[1])

或者:

vi ./*(.om[1])

只考虑常规的文件。

vi ./*(.Dom[1])

还要考虑文件(就像使用ls -At)。

无论文件名可能包含什么字符或字节值,这些都可以工作。对于与后一种等效的 GNU shell&utilities,您可以执行以下操作:

IFS= read -rd '' file < <(
  find . ! -name . -prune -type f -printf '%T@\t%p\0' | sort -zrn | cut -zf2-) &&
  vi "$file"

答案2

对于您的管道结构,您可以xargs像这样使用:

ls -1t | head -1 | xargs vi

答案3

如果您需要一个更可靠的解决方案,不依赖于片状输出,ls您可以求助于stat(1).大多数实现都有一些方法来指定自定义输出格式,其中可以包括要提供的时间戳sort(1)或 Awk 脚本。一些例子:

  • 使用 GNU coreutils:

    stat -L -c '%Y %n' -- *
    
  • 使用 BSD coreutils:

    stat -L -t '%s' -f '%Sm %N' ./*
    

随后您可以对结果进行排序和过滤:

  • 仅使用 coreutils:

    stat ... | sort -t ' ' -k 1,1 -n -r | head -n 1 | cut -d ' ' -f 2-
    

    即使您只需要最大值,这也需要 O(n log n) 时间对整个输入进行排序。

  • 使用 awk:

    stat ... | awk -F ' ' 'NR == 1 || $1 > m { m = $1; n = substr($0, length(m) + 2); } END{ if (NR) print(n); }'
    

    这会在 O(n) 时间内运行,因为它只比较并更新最大值。

相关内容