変更された日付でzsh配列をソートする方法は?

変更された日付でzsh配列をソートする方法は?

変更された日付で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.'
}

答え1

リストを作成しながらソートしておくと、はるかに簡単になると思います。。しかし、できないなら…

従来のアプローチは、データにソート基準を追加してからソートし、追加したジャンクを削除することです。タイムスタンプとファイル名を含む配列を明確にし、タイムスタンプがアルファベット順に並べ替えることができる形式で構成します。配列の並べ替え(使用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秒の解像度で比較します。多くのファイルシステムには1秒未満の解像度がありますが、stat以前のバージョンのzshではzshモジュールを使用して取得することはできません。

zshが古すぎる場合は、このstatユーティリティを使用してより正確なタイムスタンプを取得できます。GNUコアツール。お持ちの場合は、おそらく他のGNU coreutilもお持ちであるので、私はそれを使用します。 GNU coreutilsは通常非埋め込みLinuxに存在しますが、BSDやmacOSには存在しない可能性があります。 macOSでは使用できますbrew。 GNU coreutilsがデフォルトのオペレーティングシステムの一部ではない場合は、に変更する必要がstatあります。gstatsortgsortcutgcut

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

$files別のzshアプローチは、すべてのファイルなどを含むスキーマを構築することです。このパターンに一致するファイルを並べ替え、必要なファイルのみを含めるようにフィルタリングします。実際にはスキーマ全体を構築する必要がありますが、more_filesこれは必ずしも実用的ではないかもしれません。

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

答え2

次のようなものを使用できますそれ:

zmodload zsh/stat

array=(file1 file2...)

# store mtimes in an associative array:
typeset -A mtime
stat -nLF %s.%N -A mtime +mtime -- $array

# sort using the Oe glob qualifier
sorted_array=(/(e['reply=($array)']nOe['REPLY=$mtime[$REPLY]'])

%Nナノ秒にはzsh 5.6以上が必要です)。

答え3

Jeffが指摘したように、次のように整列した配列を作成する方が簡単になります。

set -A files $(ls -trd -- ~/a ~/b ~/c)

ls出力を文字ごとに分割します$IFS(デフォルトはSPC、TAB、LF、NULを含む). LFにのみ分割するには(SPCまたはTAB文字を含むファイル名を使用できますが(もちろんLFではありません))、パラメータ拡張フラグを設定またはIFS=$'\n'使用できます。f

files=(${(f)"$(ls -trd -- $files)"})

array=(...)(ここでは、ksh88スタイルの代わりにZshスタイルの構文も使用されています。set -A array ...とにかく、構文はすでにzsh専用です。)

関連情報