Es scheint, dass ls
die Dateien bei einem rekursiven Aufruf nicht richtig sortiert werden:
ls -altR . | head -n 3
Wie finde ich die zuletzt geänderte Datei in einem Verzeichnis (einschließlich Unterverzeichnissen)?
Es scheint, dass ls
die Dateien bei einem rekursiven Aufruf nicht richtig sortiert werden:
ls -altR . | head -n 3
Wie finde ich die zuletzt geänderte Datei in einem Verzeichnis (einschließlich Unterverzeichnissen)?
Antworten:
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "
Für einen riesigen Baum könnte es schwierig sein sort
, alles im Gedächtnis zu behalten.
%T@
gibt Ihnen die Änderungszeit wie ein Unix-Zeitstempel, sort -n
sortiert numerisch, tail -1
nimmt die letzte Zeile (höchster Zeitstempel) und cut -f2 -d" "
schneidet das erste Feld (den Zeitstempel) von der Ausgabe ab.
Bearbeiten: Genau wie -printf
es wahrscheinlich nur GNU ist, ist auch Ajreals Verwendung von stat -c
. Obwohl es möglich ist, dasselbe mit BSD zu tun, sind die Formatierungsoptionen unterschiedlich (wie -f "%m %N"
es scheint).
Und ich habe den Teil des Plural verpasst; Wenn Sie mehr als die neueste Datei möchten , erhöhen Sie einfach das Argument tail.
sort -rn | head -3
anstelle von wechseln sort -n | tail -3
. Eine Version gibt die Dateien vom ältesten zum neuesten, während die andere vom neuesten zum ältesten wechselt.
sort
erstellt /tmp
nach Bedarf temporäre Dateien (in ), daher denke ich nicht, dass dies ein Problem ist.
-printf '%T@ %Tb %Td %TY %p\n'
geben Ihnen einen Datumsstempel (falls erforderlich) (ähnlich ls
)
find . -type f -printf '%TF %TT %p\n' | sort | tail -1
Nach der Antwort von @ plundra finden Sie hier die BSD- und OS X-Version:
find . -type f -print0 | xargs -0 stat -f "%m %N" |
sort -rn | head -1 | cut -f2- -d" "
find
Unterstützt das BSD / OS X +
statt \;
? Denn das macht dasselbe (mehrere Dateien als Parameter übergeben), ohne die -print0 | xargs -0
Pipe.
head -1
zuhead -5
Anstatt die Ergebnisse zu sortieren und nur die zuletzt geänderten beizubehalten, können Sie mit awk nur das Ergebnis mit der größten Änderungszeit (in Unix-Zeit) drucken:
find . -type f -printf "%T@\0%p\0" | awk '
{
if ($0>max) {
max=$0;
getline mostrecent
} else
getline
}
END{print mostrecent}' RS='\0'
Dies sollte ein schnellerer Weg sein, um Ihr Problem zu lösen, wenn die Anzahl der Dateien groß genug ist.
Ich habe das NUL-Zeichen (dh '\ 0') verwendet, da ein Dateiname theoretisch jedes beliebige Zeichen (einschließlich Leerzeichen und Zeilenumbruch) enthalten kann.
Wenn Sie keine solchen pathologischen Dateinamen in Ihrem System haben, können Sie auch das Zeilenumbruchzeichen verwenden:
find . -type f -printf "%T@\n%p\n" | awk '
{
if ($0>max) {
max=$0;
getline mostrecent
} else
getline
}
END{print mostrecent}' RS='\n'
Darüber hinaus funktioniert dies auch in Mawk.
mawk
der Debian-Standardalternative.
Ich hatte Probleme, die zuletzt geänderte Datei unter Solaris 10 zu finden. Es find
gibt keine printf
Option und sie stat
ist nicht verfügbar. Ich habe die folgende Lösung gefunden, die für mich gut funktioniert:
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7 }' | sort | tail -1
Um auch den Dateinamen anzuzeigen, verwenden Sie
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7," ",$9 }' | sort | tail -1
Erläuterung
find . -type f
findet und listet alle Dateien aufsed 's/.*/"&"/'
Umschließt den Pfadnamen in Anführungszeichen, um Leerzeichen zu verarbeitenxargs ls -E
Wenn der angegebene Pfad an gesendet wird, ls
stellt die -E
Option sicher, dass ein vollständiger Zeitstempel (Format Jahr-Monat-Tag Stunde-Minute-Sekunden-Nanosekunden ) zurückgegeben wirdawk '{ print $6," ",$7 }'
extrahiert nur Datum und Uhrzeitawk '{ print $6," ",$7," ",$9 }'
extrahiert Datum, Uhrzeit und Dateinamensort
Gibt die nach Datum sortierten Dateien zurücktail -1
Gibt nur die zuletzt geänderte Datei zurückDies scheint auch mit Unterverzeichnissen gut zu funktionieren:
find . -type f | xargs ls -ltr | tail -n 1
Bei zu vielen Dateien verfeinern Sie den Fund.
-l
Option zu ls
erscheint unnötig. Scheint einfach -tr
ausreichend.
find . -type f -print0 | xargs -0 ls -ltr | tail -n 1
Zeigt die neueste Datei mit lesbarem Zeitstempel an:
find . -type f -printf '%TY-%Tm-%Td %TH:%TM: %Tz %p\n'| sort -n | tail -n1
Ergebnis sieht so aus:
2015-10-06 11:30: +0200 ./foo/bar.txt
Um mehr Dateien anzuzeigen, ersetzen Sie diese -n1
durch eine höhere Nummer
Ich verwende ständig etwas Ähnliches sowie die Top-K-Liste der zuletzt geänderten Dateien. Bei großen Verzeichnisbäumen kann es viel schneller sein, eine Sortierung zu vermeiden . Im Fall der zuletzt geänderten Top-1-Datei:
find . -type f -printf '%T@ %p\n' | perl -ne '@a=split(/\s+/, $_, 2); ($t,$f)=@a if $a[0]>$t; print $f if eof()'
In einem Verzeichnis mit 1,7 Millionen Dateien erhalte ich das neueste in 3.4s, eine Beschleunigung von 7.5x gegenüber der 25.5s-Lösung mit sort.
lastfile
) und dann mit dem Ergebnis tun, was Sie möchten, z. B. ls -l $(lastfile .)
oder open $(lastfile .)
(auf einem Mac) usw.
Unter Ubuntu 13 funktioniert dies im Folgenden möglicherweise etwas schneller, da die Sortierung umgekehrt wird und "Kopf" anstelle von "Schwanz" verwendet wird, wodurch die Arbeit reduziert wird. So zeigen Sie die 11 neuesten Dateien in einem Baum an:
finden . -Typ f -printf '% T @% p \ n' | sort -n -r | Kopf -11 | cut -f2- -d "" | sed -e 's, ^. / ,,' | xargs ls -U -l
Dies ergibt eine vollständige ls-Liste ohne erneutes Sortieren und lässt das nervige './' weg, das 'find' auf jeden Dateinamen setzt.
Oder als Bash-Funktion:
treecent () {
local numl
if [[ 0 -eq $# ]] ; then
numl=11 # Or whatever default you want.
else
numl=$1
fi
find . -type f -printf '%T@ %p\n' | sort -n -r | head -${numl} | cut -f2- -d" " | sed -e 's,^\./,,' | xargs ls -U -l
}
Der größte Teil der Arbeit wurde jedoch mit der ursprünglichen Lösung von plundra erledigt. Danke plundra.
Ich stand vor dem gleichen Problem. Ich muss die neueste Datei rekursiv finden. Die Suche dauerte ungefähr 50 Minuten.
Hier ist ein kleines Skript, um es schneller zu machen:
#!/bin/sh
CURRENT_DIR='.'
zob () {
FILE=$(ls -Art1 ${CURRENT_DIR} | tail -n 1)
if [ ! -f ${FILE} ]; then
CURRENT_DIR="${CURRENT_DIR}/${FILE}"
zob
fi
echo $FILE
exit
}
zob
Es ist eine rekursive Funktion, die das zuletzt geänderte Element eines Verzeichnisses abruft. Wenn es sich bei diesem Element um ein Verzeichnis handelt, wird die Funktion rekursiv aufgerufen und in diesem Verzeichnis usw. gesucht.
Ich finde folgendes kürzer und mit besser interpretierbarer Ausgabe:
find . -type f -printf '%TF %TT %p\n' | sort | tail -1
Angesichts der festen Länge der standardisierten Datumszeiten im ISO-Format ist die lexikografische Sortierung in Ordnung und wir benötigen keine -n
Option für die Sortierung.
Wenn Sie die Zeitstempel wieder entfernen möchten, können Sie Folgendes verwenden:
find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '
Wenn das Ausführen stat
jeder einzelnen Datei zu langsam ist, können Sie die xargs
Dinge etwas beschleunigen:
find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -n | tail -1 | cut -f2- -d" "
Dadurch wird die Änderungszeit aller Verzeichnisse im aktuellen Verzeichnis rekursiv in die neueste Datei in jedem Verzeichnis geändert:
for dir in */; do find $dir -type f -printf '%T@ "%p"\n' | sort -n | tail -1 | cut -f2- -d" " | xargs -I {} touch -r {} $dir; done
Diese einfache Cli wird auch funktionieren:
ls -1t | head -1
Sie können -1 in die Anzahl der Dateien ändern, die Sie auflisten möchten
Ich fand den obigen Befehl nützlich, aber für meinen Fall musste ich auch das Datum und die Uhrzeit der Datei sehen. Ich hatte ein Problem mit mehreren Dateien, deren Namen Leerzeichen enthalten. Hier ist meine Arbeitslösung.
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l
$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10
Behandelt Leerzeichen in Dateinamen gut - nicht, dass diese verwendet werden sollten!
2017.01.25 18h23 Wed ./indenting/Shifting blocks visually.mht
2016.12.11 12h33 Sun ./tabs/Converting tabs to spaces.mht
2016.12.02 01h46 Fri ./advocacy/2016.Vim or Emacs - Which text editor do you prefer?.mht
2016.11.09 17h05 Wed ./Word count - Vim Tips Wiki.mht
Mehr in find
Hülle und Fülle folgen Sie dem Link.
So suchen Sie nach Dateien in / target_directory und allen Unterverzeichnissen, die in den letzten 60 Minuten geändert wurden:
$ find /target_directory -type f -mmin -60
So finden Sie die zuletzt geänderten Dateien in umgekehrter Reihenfolge der Aktualisierungszeit (dh zuerst die zuletzt aktualisierten Dateien):
$ find /etc -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r
Ich bevorzuge dieses, es ist kürzer:
find . -type f -print0|xargs -0 ls -drt|tail -n 1
Ich habe ein Pypi / Github-Paket für diese Frage geschrieben, weil ich auch eine Lösung brauchte.
https://github.com/bucknerns/logtail
Installieren:
pip install logtail
Verwendung: Schwänze geänderte Dateien
logtail <log dir> [<glob match: default=*.log>]
Verwendung2: Öffnet die zuletzt geänderte Datei im Editor
editlatest <log dir> [<glob match: default=*.log>]