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.