如何按修改日期对 zsh 数组进行排序?

Hap*_*ace 3 zsh array date sort files

如何按修改日期对 zsh 数组进行排序?

files=( ~/a ~/b ~/c )
# how to sort files by date?
Run Code Online (Sandbox Code Playgroud)

PS:这是我的确切用例,(fz几乎fzf

v () {
 local files
 files=() 
 command rg '^>' ~/.viminfo | cut -c3- | while read line
 do
  [ -f "${line/\~/$HOME}" ] && files+="$line" 
 done
 test -f ~/.emacs.d/.cache/recentf && {
  command rg --only-matching --replace '$1' '^\s*"(.*)"$' ~/.emacs.d/.cache/recentf | while read line
  do
   [ -f "$line" ] && files+="$line" 
  done
 }
 files="$(<<<"${(F)files}" fz --print0 --query "$*")"  || return 1
 files="${files//\~/$HOME}" 
 local ve="$ve" 
 test -z "$ve" && ! isSSH && ve=nvim 
 "${ve:-vim}" -p ${(0@)files}
 : '-o opens in split view, -p in tabs. Use gt, gT, <num>gt to navigate tabs.'
}
Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 7

如果在构建列表时对列表进行排序,就会容易得多。但如果你不能\xe2\x80\xa6

\n\n

一种经典的方法是向数据添加排序标准,然后对其进行排序,然后删除添加的垃圾。以明确的方式构建一个包含时间戳和文件名的数组,并且时间戳的格式可以按字典顺序排序。对数组进行排序(使用o 参数扩展标志),然后去除前缀。您可以使用该stat模块来获取文件的修改时间。

\n\n
zmodload zsh/stat\nfor ((i=1; i<$#files; i++)); do times[$i]=$(stat -g -F %020s%N +mtime -L -- $files[$i]):$files[$i]; done\nsorted=(${${(o)times}#*:})\n
Run Code Online (Sandbox Code Playgroud)\n\n

zstat 的格式%N(以纳秒分辨率获取时间戳)需要 zsh \xe2\x89\xa55.6。如果您的 zsh 较旧,请将其删除,代码仍然可以工作,但以 1 秒的分辨率比较时间戳。许多文件系统都有亚秒分辨率,但我认为您无法使用stat旧版本 zsh 中的 zsh 模块获得它。

\n\n

如果您的 zsh 太旧,您可以使用GNU coreutilsstat的实用程序获得更精确的时间戳。如果你有它,你可能也有其他 GNU coreutils,所以我将使用它们。GNU coreutils 通常存在于非​​嵌入式 Linux 上,但可能不存在于 BSD 或 macOS 上。在 macOS 上,您可以使用. 如果 GNU coreutils 不是基本操作系统的一部分,您可能需要更改为、和。brewstatgstatsortgsortcutgcut

\n\n
if (($#files)); then\n  sorted=(${(0@)"$(stat  --printf=\'%040.18Y:%n\\0\' "$files[@]" | sort -rz | cut -z -d\':\' -f2-)"})\nelse\n  sorted=()\nfi\n
Run Code Online (Sandbox Code Playgroud)\n\n

另一种 zsh 方法是构建一个包含所有文件$files以及更多内容的模式。对匹配此模式的文件进行排序,然后对其进行过滤以仅包含所需的文件。您确实需要为 构建整个模式more_files,这可能并不总是实用的。

\n\n
more_files=(~/*(Om))\nsorted=(${more_files:*files})\n
Run Code Online (Sandbox Code Playgroud)\n