Wie sortiert man ein Zsh-Array nach Änderungsdatum?

Wie sortiert man ein Zsh-Array nach Änderungsdatum?

Wie sortiert man ein Zsh-Array nach Änderungsdatum?

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

PS: Hier ist mein genauer Anwendungsfall ( fzist fast 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.'
}

Antwort1

Es ist viel einfacher, wenn Sie die Liste beim Erstellen sortierenAber wenn Sie nicht können …

Ein klassischer Ansatz besteht darin, den Daten das Sortierkriterium hinzuzufügen, sie dann zu sortieren und dann den hinzugefügten Ballast zu entfernen. Erstellen Sie ein Array mit Zeitstempeln und Dateinamen in einer eindeutigen Weise und mit den Zeitstempeln in einem Format, das lexikografisch sortiert werden kann. Sortieren Sie das Array (mit demo Parametererweiterungsflag), dann entfernen Sie das Präfix. Sie können diestatModul, um die Änderungszeit der Datei zu erhalten.

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}#*:})

Das %NFormat für zstat (um Zeitstempel mit einer Auflösung von Nanosekunden zu erhalten) erfordert zsh ≥5.6. Wenn Ihr zsh älter ist, entfernen Sie es und der Code funktioniert weiterhin, vergleicht jedoch Zeitstempel mit einer Auflösung von 1 Sekunde. Viele Dateisysteme haben eine Auflösung von unter einer Sekunde, aber ich glaube nicht, dass Sie diese mit dem zsh- statModul in älteren Versionen von zsh erreichen können.

Wenn Ihr zsh zu alt ist, können Sie genauere Zeitstempel mit dem statDienstprogramm von erhaltenGNU-Kerndienstprogramme. Wenn Sie es haben, haben Sie wahrscheinlich auch die anderen GNU-Coreutils, daher werde ich diese verwenden. GNU-Coreutils sind normalerweise auf nicht eingebettetem Linux vorhanden, aber möglicherweise nicht auf BSD oder macOS. Auf macOS können Sie sie mit installieren brew. Wenn die GNU-Coreutils nicht Teil des Basisbetriebssystems sind, müssen Sie möglicherweise statin gstat, sortin gsortund cutin ändern gcut.

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

Ein alternativer zsh-Ansatz besteht darin, ein Muster zu erstellen, das alle Dateien in $filesund mehr enthält. Sortieren Sie die Dateien, die diesem Muster entsprechen, und filtern Sie es dann, um nur die gewünschten Dateien einzuschließen. Sie müssen das gesamte Muster für erstellen more_files, was nicht immer praktikabel ist.

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

Antwort2

Sie können einen Ansatz verwenden, der dem vonDas hier:

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]'])

( %Nfür Nanosekunden ist zsh 5.6 oder neuer erforderlich).

Antwort3

Wie Jeff betonte, ist es einfacher, Ihr Array sortiert zu erstellen, wie in:

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

Hier wird die Ausgabe lsnach $IFSZeichen aufgeteilt (standardmäßig enthält sie SPC, TAB, LF und NUL). Um nur nach LF aufzuteilen (um mit Dateinamen arbeiten zu können, die SPC- oder TAB-Zeichen enthalten (aber offensichtlich nicht LF)), können Sie das Parametererweiterungsflag setzen IFS=$'\n'oder verwenden :f

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

(hier wird auch die Syntax im zsh-Stil array=(...)anstelle der im ksh88-Stil verwendet set -A array ..., da diese Syntax ohnehin bereits zsh-spezifisch ist).

verwandte Informationen