Es scheint, dass ls
die Dateien beim rekursiven Aufruf nicht korrekt sortiert:
ls -altR . | head -n 3
Wie finde ich die zuletzt geänderte Datei in einem Verzeichnis (einschließlich Unterverzeichnissen)?
find . -type f -printf '%[email protected] %p\n' | sort -n | tail -1 | cut -f2- -d" "
Für einen großen Baum ist es für sort
möglicherweise schwierig, alles im Speicher zu behalten.
%[email protected]
gibt die Änderungszeit wie ein Unix-Zeitstempel an, sort -n
sortiert numerisch, tail -1
nimmt die letzte Zeile (höchster Zeitstempel), cut -f2 -d" "
schneidet das erste Feld (den Zeitstempel) von der Ausgabe ab.
Edit: So wie -printf
wahrscheinlich nur GNU ist, ist auch die Verwendung von stat -c
bei ajreals. Obwohl es möglich ist, dasselbe mit BSD zu tun, sind die Optionen für die Formatierung unterschiedlich (-f "%m %N"
).
Und ich habe den Teil des Plural vermisst; Wenn Sie mehr als die neueste -Datei wünschen, müssen Sie nur das Tail-Argument aufstocken.
Folgend auf @ plundras Antwort , hier die BSD- und OS X-Version:
find . -type f -print0 | xargs -0 stat -f "%m %N" |
sort -rn | head -1 | cut -f2- -d" "
Anstatt die Ergebnisse zu sortieren und nur die zuletzt geänderten zu behalten, können Sie mit awk nur diejenige mit der größten Änderungszeit (in Unix-Zeit) drucken:
find . -type f -printf "%[email protected]\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 (d. H. '\ 0') verwendet, da ein Dateiname theoretisch ein beliebiges Zeichen (einschließlich Leerzeichen und Zeilenumbrüche) enthalten kann.
Wenn Sie in Ihrem System keine solchen pathologischen Dateinamen haben, können Sie auch das Zeilenvorschubzeichen verwenden:
find . -type f -printf "%[email protected]\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.
Ich hatte die Mühe, die zuletzt geänderte Datei unter Solaris 10 zu finden. Dort hat find
nicht die Option printf
und 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 den Dateinamen anzuzeigen, verwenden Sie
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7," ",$9 }' | sort | tail -1
Erklärung
find . -type f
findet alle Dateien und listet sie aufsed 's/.*/"&"/'
umgibt den Pfadnamen in Anführungszeichen, um Whitespaces zu behandelnxargs ls -E
sendet den angegebenen Pfad an ls
. Die Option -E
stellt 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 Dateinamesort
gibt die Dateien nach Datum sortiert zurücktail -1
gibt nur die zuletzt geänderte Datei zurückDies scheint auch bei Unterverzeichnissen gut zu funktionieren:
find . -type f | xargs ls -ltr | tail -n 1
Bei zu vielen Dateien den Suchvorgang verfeinern.
Zeigt die neueste Datei mit vom Menschen lesbarer Zeitmarke 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
Ersetzen Sie -n1
durch eine höhere Nummer, um weitere Dateien anzuzeigen
Dies ergibt eine sortierte Liste:
find . -type f -ls 2>/dev/null | sort -M -k8,10 | head -n5
Kehren Sie die Reihenfolge um, indem Sie im Sortierbefehl ein '-r' eingeben. Wenn Sie nur Dateinamen wünschen, fügen Sie "awk '{print $ 11}' |" ein. vor '| Kopf'
Auf Ubuntu 13 ist Folgendes möglich, vielleicht ein bisschen 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 einer Baumstruktur an:
finden . -type f -printf '% T @% p\n' | sort -n -r | Kopf -11 | cut -f2- -d "" | sed -e 's, ^./,' | xargs ls -U -l
Dies führt zu einer vollständigen ls-Auflistung ohne Umsortieren und das lästige './', das 'find' für jeden Dateinamen verwendet, wird weggelassen.
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 '%[email protected] %p\n' | sort -n -r | head -${numl} | cut -f2- -d" " | sed -e 's,^\./,,' | xargs ls -U -l
}
Die meiste Arbeit wurde jedoch mit der ursprünglichen Lösung von plundra erledigt. Danke, Plundra.
Wenn Sie stat
für jede Datei einzeln ausführen, können Sie mit xargs
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 auf die neueste Datei in jedem Verzeichnis rekursiv geändert:
for dir in */; do find $dir -type f -printf '%[email protected] "%p"\n' | sort -n | tail -1 | cut -f2- -d" " | xargs -I {} touch -r {} $dir; done
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, um das Sortieren zu vermeiden. Im Falle der Top-1-Datei, die zuletzt geändert wurde:
find . -type f -printf '%[email protected] %p\n' | Perl -ne '@a=split(/\s+/, $_, 2); ($t,$f)[email protected] if $a[0]>$t; print $f if eof()'
In einem Verzeichnis mit 1,7 Millionen Dateien bekomme ich die neueste in 3.4s, eine Beschleunigung von 7.5x gegenüber der 25.5s-Lösung mit sort.
Ich stand vor demselben Problem. Ich muss die neueste Datei rekursiv finden. Die Suche dauerte etwa 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 dieses Verzeichnis usw. durchsucht.
Dieses einfache cli funktioniert auch:
ls -1t | head -1
Sie können -1 in die Anzahl der Dateien ändern, die Sie auflisten möchten
Der folgende Befehl funktioniert unter Solaris:
find . -name "*Zip" -type f | xargs ls -ltr | tail -1
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 ISO-Formatdaten ist die lexikografische Sortierung in Ordnung und wir brauchen die -n
-Option nicht 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' '
So suchen Sie nach Dateien in/target_directory und all seinen 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, die in umgekehrter Reihenfolge der Aktualisierungszeit sortiert sind (d. H. Die zuletzt aktualisierten Dateien zuerst):
$ find /etc -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r
$ 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
Mehrfind
in Hülle und Fülle dem Link folgen.
Ich fand den Befehl oben nützlich, aber für meinen Fall musste ich Datum und Uhrzeit der Datei anzeigen. Außerdem hatte ich ein Problem mit mehreren Dateien, die Leerzeichen in den Namen enthalten.
find . -type f -printf '%[email protected] %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l
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: Endet geänderte Dateien
logtail <log dir> [<glob match: default=*.log>]
Usage2: Öffnet die zuletzt geänderte Datei im Editor
editlatest <log dir> [<glob match: default=*.log>]
Ich bevorzuge dieses, es ist kürzer:
find . -type f -print0|xargs -0 ls -drt|tail -n 1