Die Kombination von find
und ls
funktioniert gut für
- Dateinamen ohne Zeilenumbrüche
- nicht sehr viele Dateien
- nicht sehr lange Dateinamen
Die Lösung:
find . -name "my-pattern" -print0 |
xargs -r -0 ls -1 -t |
head -1
Lassen Sie es uns aufschlüsseln:
Mit find
wir können alle interessanten Dateien wie folgt abgleichen:
find . -name "my-pattern" ...
dann mit -print0
wir können alle Dateinamen sicher an ls
übergeben so:
find . -name "my-pattern" -print0 | xargs -r -0 ls -1 -t
zusätzlich find
Suchparameter und Muster können hier hinzugefügt werden
find . -name "my-pattern" ... -print0 | xargs -r -0 ls -1 -t
ls -t
sortiert Dateien nach Änderungszeit (neueste zuerst) und druckt sie eine nach der anderen. Sie können -c
verwenden nach Erstellungszeit zu sortieren. Hinweis :Dies wird bei Dateinamen mit Zeilenumbrüchen unterbrochen.
Schließlich head -1
liefert uns die erste Datei in der sortierten Liste.
Hinweis: xargs
Verwenden Sie Systemgrenzen für die Größe der Argumentliste. Wenn diese Größe überschritten wird, xargs
ruft ls
an mehrmals. Dadurch wird die Sortierung und wahrscheinlich auch die endgültige Ausgabe unterbrochen. Führen Sie
xargs --show-limits
um die Limits auf Ihrem System zu überprüfen.
Anmerkung 2: Verwenden Sie find . -maxdepth 1 -name "my-pattern" -print0
wenn Sie Dateien nicht in Unterordnern durchsuchen möchten.
Anmerkung 3: Wie von @starfry hervorgehoben - -r
Argument für xargs
verhindert den Aufruf von ls -1 -t
, wenn dem find
keine Dateien zugeordnet wurden . Vielen Dank für den Vorschlag.
Die ls
Befehl hat einen Parameter -t
nach Zeit sortieren. Sie können dann mit head -1
die erste (neueste) abrufen .
ls -t b2* | head -1
Aber Achtung:Warum Sie die Ausgabe von ls nicht parsen sollten
Meine persönliche Meinung:Parsen von ls
ist nur gefährlich, wenn die Dateinamen komische Zeichen wie Leerzeichen oder Zeilenumbrüche enthalten können. Wenn Sie garantieren können, dass die Dateinamen keine komischen Zeichen enthalten, dann parsen Sie ls
ist ziemlich sicher.
Wenn Sie ein Skript entwickeln, das von vielen Leuten auf vielen Systemen in vielen verschiedenen Situationen ausgeführt werden soll, empfehle ich dringend, ls
nicht zu parsen .
So machen Sie es "richtig":Wie finde ich die neueste (neueste, früheste, älteste) Datei in einem Verzeichnis?
unset -v latest
for file in "$dir"/*; do
[[ $file -nt $latest ]] && latest=$file
done
Dies ist eine mögliche Implementierung der erforderlichen Bash-Funktion:
# Print the newest file, if any, matching the given pattern
# Example usage:
# newest_matching_file 'b2*'
# WARNING: Files whose names begin with a dot will not be checked
function newest_matching_file
{
# Use ${1-} instead of $1 in case 'nounset' is set
local -r glob_pattern=${1-}
if (( $# != 1 )) ; then
echo 'usage: newest_matching_file GLOB_PATTERN' >&2
return 1
fi
# To avoid printing garbage if no files match the pattern, set
# 'nullglob' if necessary
local -i need_to_unset_nullglob=0
if [[ ":$BASHOPTS:" != *:nullglob:* ]] ; then
shopt -s nullglob
need_to_unset_nullglob=1
fi
newest_file=
for file in $glob_pattern ; do
[[ -z $newest_file || $file -nt $newest_file ]] \
&& newest_file=$file
done
# To avoid unexpected behaviour elsewhere, unset nullglob if it was
# set by this function
(( need_to_unset_nullglob )) && shopt -u nullglob
# Use printf instead of echo in case the file name begins with '-'
[[ -n $newest_file ]] && printf '%s\n' "$newest_file"
return 0
}
Es verwendet nur eingebaute Bash-Ins und sollte mit Dateien umgehen, deren Namen Zeilenumbrüche oder andere ungewöhnliche Zeichen enthalten.