変更された日付で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
あります。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
$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専用です。)