Files

如何按修改日期對 zsh 數組進行排序?

  • April 9, 2020

如何按修改日期對 zsh 數組進行排序?

files=( ~/a ~/b ~/c )
# how to sort files by date?

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.'
}

如果在建構列表時對列表進行排序,會容易得多。但如果你不能……

一種經典的方法是將排序標準添加到數據中,然後對其進行排序,然後刪除添加的雜物。以明確的方式建構一個包含時間戳和文件名的數組,並且時間戳的格式可以按字典順序排序。對數組進行排序(使用o 參數擴展標誌),然後去除前綴。您可以使用該stat模組獲取文件的修改時間。

zmodload zsh/stat
for ((i=1; i<$#files; i++)); do times[$i]=$(stat -g -F %020s%N +mtime -L -- $files[$i]):$files[$i]; done
sorted=(${${(o)times}#*:})

zstat的%N格式(以納秒解析度獲取時間戳)需要 zsh ≥5.6。如果您的 zsh 較舊,請將其刪除,程式碼仍然可以工作,但以 1 秒的解析度比較時間戳。許多文件系統具有亞秒級解析度,但我認為您無法使用stat舊版本 zsh 中的 zsh 模組獲得它。

如果您的 zsh 太舊,您可以使用GNU coreutilsstat的實用程序獲得更精確的時間戳。如果你有它,你可能也有其他的 GNU coreutils,所以我會使用它們。GNU coreutils 通常出現在非嵌入式 Linux 上,但可能不在 BSD 或 macOS 上。在 macOS 上,您可以使用. 如果 GNU coreutils 不是基本作業系統的一部分,您可能需要更改為、和。brew``stat``gstat``sort``gsort``cut``gcut

if (($#files)); then
 sorted=(${(0@)"$(stat  --printf='%040.18Y:%n\0' "$files[@]" | sort -rz | cut -z -d':' -f2-)"})
else
 sorted=()
fi

另一種 zsh 方法是建構一個包含所有文件$files和更多文件的模式。對匹配此模式的文件進行排序,然後對其進行過濾以僅包含所需的文件。您確實需要為 建構整個模式more_files,這可能並不總是實用的。

more_files=(~/*(Om))
sorted=(${more_files:*files})

引用自:https://unix.stackexchange.com/questions/578522